-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathlang.l
202 lines (181 loc) · 6.08 KB
/
lang.l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ast.h"
#include "lang.tab.h"
VarType current_var_type = NONE;
char *unescape_string(const char *src) {
// Allocate a buffer big enough for the worst case
// (same length as src, since we only shrink on escapes)
char *dest = malloc(strlen(src) + 1);
char *d = dest;
const char *s = src;
while (*s) {
if (*s == '\\') {
s++;
switch (*s) {
case 'n': *d++ = '\n'; break;
case 't': *d++ = '\t'; break;
case '\\': *d++ = '\\'; break;
case '"': *d++ = '"'; break;
// ... handle other escapes you care about ...
default:
// If it's an unknown escape like \q,
// you might just copy it literally or skip it.
*d++ = *s;
break;
}
s++;
} else {
*d++ = *s++;
}
}
*d = '\0';
return dest;
}
extern int yylineno;
%}
%option yylineno
%%
"skibidi" { return SKIBIDI; }
"bussin" { return BUSSIN; }
"flex" { return FLEX; }
"rizz" { current_var_type = VAR_INT; return RIZZ; }
"main" { return MAIN; }
"bruh" { return BREAK; }
"sigma rule" { return CASE; }
"yap" { current_var_type = VAR_CHAR; return YAP; }
"deadass" { return DEADASS; }
"grind" { return CONTINUE; }
"based" { return DEFAULT; }
"mewing" { return DO; }
"gigachad" { current_var_type = VAR_DOUBLE; return GIGACHAD; }
"gyatt" { return ENUM; }
"whopper" { return EXTERN; }
"chad" { current_var_type = VAR_FLOAT; return CHAD; }
"cringe" { return GOTO; }
"edgy" { return IF; }
"amogus" { return ELSE; }
"giga" { return LONG; }
"smol" { current_var_type = VAR_SHORT; return SMOL; }
"nut" { return SIGNED; }
"maxxing" { return SIZEOF; }
"salty" { return STATIC; }
"gang" { return STRUCT; }
"ohio" { return SWITCH; }
"chungus" { return UNION; }
"nonut" { return UNSIGNED; }
"schizo" { return VOLATILE; }
"goon" { return GOON; }
"baka" { return BAKA; }
"cap" { current_var_type = VAR_BOOL; return CAP; }
"==" { return EQ; }
"!=" { return NE; }
"<=" { return LE; }
">=" { return GE; }
"&&" { return AND; }
"||" { return OR; }
"<" { return LT; }
">" { return GT; }
"=" { return EQUALS; }
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return TIMES; }
"/" { return DIVIDE; }
"%" { return MOD; }
"++" { return INC; }
"--" { return DEC; }
"(" { return LPAREN; }
")" { return RPAREN; }
"{" { return LBRACE; }
"}" { return RBRACE; }
";" { return SEMICOLON; }
"," { return COMMA; }
":" { return COLON; }
"[" { return LBRACKET; }
"]" { return RBRACKET; }
"🚽"[^\n]* ; /* Ignore single line comments */
"W" { yylval.ival = 1; return BOOLEAN; }
"L" { yylval.ival = 0; return BOOLEAN; }
[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[LlFf]? {
char *endptr;
if (strchr(yytext, 'f') || strchr(yytext, 'F')) {
yylval.fval = strtof(yytext, &endptr);
return FLOAT_LITERAL;
} else if (strchr(yytext, 'L') || strchr(yytext, 'l')) {
yylval.dval = strtod(yytext, &endptr);
return DOUBLE_LITERAL;
} else {
yylval.dval = strtod(yytext, &endptr);
return DOUBLE_LITERAL;
}
}
[0-9]+ {
int next_char = input(); // Peek at the next character
unput(next_char); // Put it back into the input stream
if (next_char == ']') {
// If the next character is ']', treat this numeric literal as an integer.
yylval.ival = atoi(yytext);
return INT_LITERAL;
}
// Otherwise, follow the existing type-based logic.
if (current_var_type == VAR_SHORT) {
yylval.sval = (short)atoi(yytext);
return SHORT_LITERAL;
} else if (current_var_type == VAR_INT) {
yylval.ival = atoi(yytext);
return INT_LITERAL;
} else if (current_var_type == VAR_FLOAT) {
yylval.fval = atof(yytext);
return FLOAT_LITERAL;
} else if (current_var_type == VAR_DOUBLE) {
yylval.dval = (double)atof(yytext);
return DOUBLE_LITERAL;
} else {
yylval.ival = atoi(yytext);
return INT_LITERAL;
}
}
'.' { yylval.ival = yytext[1]; return CHAR; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.strval = strdup(yytext); return IDENTIFIER; }
\"([^\\\"]|\\.)*\" {
// Strip the leading and trailing quotes:
char *raw = strdup(yytext + 1);
raw[strlen(raw) - 1] = '\0';
// Convert backslash escapes to real characters:
char *unescaped = unescape_string(raw);
free(raw);
yylval.strval = unescaped; // Now it has real newlines, etc.
return STRING_LITERAL;
}
\'([^\\\']|\\.)\' {
// The text matched includes the leading and trailing single quotes, e.g. 'c'.
// We'll decode the actual character inside.
char c;
if (yytext[1] == '\\') {
// Handle escape sequences like '\n', '\t', '\\', '\''
switch (yytext[2]) {
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
case '\\': c = '\\'; break;
case '\'': c = '\''; break;
// You can add more escapes if you need them
default:
// If unrecognized, just use the literal char
c = yytext[2];
break;
}
} else {
// Normal single character, e.g. 'c'
c = yytext[1];
}
yylval.ival = c; // Put the character in the parser’s yylval
return YAP;
}
[ \t\n]+ ; /* Ignore whitespace */
. { /* Ignore unrecognized characters */ }
%%
int yywrap(void) {
return 1;
}