-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtil_scanner.l
135 lines (103 loc) · 3.91 KB
/
til_scanner.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
%option c++ prefix="til_scanner_" outfile="til_scanner.cpp"
%option stack noyywrap yylineno 8bit debug
%{
// make relevant includes before including the parser's tab file
#include <string>
#include <cdk/ast/sequence_node.h>
#include <cdk/ast/expression_node.h>
#include <cdk/ast/lvalue_node.h>
#include "til_parser.tab.h"
// don't change this
#define yyerror LexerError
#define CHECKED_STOI(base) { \
try { \
yylval.i = std::stoi(yytext, nullptr, base); \
return tINTEGER; \
} catch (const std::out_of_range&) { \
yyerror("integer overflow"); \
} \
}
#define CHECKED_STOD { \
try { \
yylval.d = std::stod(yytext); \
return tDOUBLE; \
} catch (const std::out_of_range&) { \
yyerror("double overflow"); \
} \
}
%}
EXP [Ee][+-]?[0-9]+
%x X_STRING X_COMMENT X_STRING_END
%%
yydebug=1; set_debug(1);
";".* ; /* ignore comments */
"/*" yy_push_state(X_COMMENT);
<X_COMMENT>"*/" yy_pop_state();
<X_COMMENT>"/*" yy_push_state(X_COMMENT);
<X_COMMENT>.|\n ; /* ignore */
">=" return tGE;
"<=" return tLE;
"==" return tEQ;
"!=" return tNE;
"&&" return tAND;
"||" return tOR;
"int" return tTYPE_INT;
"double" return tTYPE_DOUBLE;
"string" return tTYPE_STRING;
"void" return tTYPE_VOID;
"external" return tEXTERNAL;
"forward" return tFORWARD;
"public" return tPUBLIC;
"var" return tVAR;
"block" return tBLOCK;
"if" return tIF;
"loop" return tLOOP;
"stop" return tSTOP;
"next" return tNEXT;
"return" return tRETURN;
"print" return tPRINT;
"println" return tPRINTLN;
"read" return tREAD;
"null" return tNULL;
"set" return tSET; /* TODO: return *yytext???*/
"index" return tINDEX;
"objects" return tOBJECTS;
"sizeof" return tSIZEOF;
"function" return tFUNCTION;
"program" return tPROGRAM;
[A-Za-z][A-Za-z0-9]* yylval.s = new std::string(yytext); return tIDENTIFIER;
\" yy_push_state(X_STRING); yylval.s = new std::string("");
<X_STRING>\" yy_pop_state(); return tSTRING;
<X_STRING>\\\" *yylval.s += yytext + 1;
<X_STRING>\\\\ *yylval.s += yytext + 1;
<X_STRING>\\t *yylval.s += '\t';
<X_STRING>\\n *yylval.s += '\n';
<X_STRING>\\r *yylval.s += '\r';
<X_STRING>\\0 yy_push_state(X_STRING_END);
<X_STRING>\\[0]{2,3} yyerror("invalid octal escape sequence");
<X_STRING>\\[0-7]{1,3} {
int i = std::stoi(yytext + 1, nullptr, 8);
if (i > 255) yyerror("octal escape sequence out of range");
*yylval.s += (char) i;
}
<X_STRING>\\. *yylval.s += yytext + 1;
<X_STRING>\n yyerror("newline in string");
<X_STRING>\0 yyerror("null byte in string");
<X_STRING>. *yylval.s += yytext;
<X_STRING_END>\" yy_pop_state(); yy_pop_state(); return tSTRING;
<X_STRING_END>\\\" ;
<X_STRING_END>\\\\ ;
<X_STRING_END>\n yyerror("newline in string");
<X_STRING_END>\0 yyerror("null byte in string");
<X_STRING_END>. ;
0|[1-9][0-9]* CHECKED_STOI(10);
0x0+ yyerror("invalid base 16 integer literal");
0x[0-9a-fA-F]+ CHECKED_STOI(16);
0[0-9]+ yyerror("invalid base 8 integer literal");
[0-9]*\.[0-9]+{EXP}? CHECKED_STOD;
[0-9]+\.[0-9]*{EXP}? CHECKED_STOD;
[0-9]+{EXP} CHECKED_STOD;
[-()<>+*/%;{},\[\]!@?~] return *yytext;
[ \t\n\r]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%