-
Notifications
You must be signed in to change notification settings - Fork 2
/
decaf.y
243 lines (203 loc) · 11 KB
/
decaf.y
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
%{
#include "include/head.h" // Include some C++ headers
#include "include/ast.h" // AST's interfaces
int yyerror(string s);
int yylex(void);
using namespace std;
ASTProgramNode *root;
%}
%union
{
int intVal;
string *strVal;
ASTProgramNode* prog;
ASTStatementDeclNode* stmt;
ASTMethodCallStatementNode *meth1;
ASTMethodDeclNode *method;
ASTBlock *bl;
ASTParameterDecl *param;
list<ASTParameterDecl *> *paramList;
list<ASTMethodDeclNode *> *methList;
list<ASTStatementDeclNode*> *stmtlist;
Symbol* sym;
list<Symbol*> *symlist;
ASTIntegerLiteralExpressionNode* intLit;
ASTLocationNode* loc;
ASTExpressionNode* expr;
list<ASTExpressionNode *> *exprList;
ASTBinaryExpressionNode* binexpr;
list<ASTCalloutArg *> *carglist;
ASTCalloutArg* carg;
}
%start Program
%token CHAR_LITERAL STRING_LITERAL TYPES BOOL_LITERAL
%token ID DEC_LITERAL HEX_LITERAL INTEGER BOOLEAN
%token HEADER CALLOUT VOID IF ELSE CONTINUE BREAK RETURN FOR
%token AND OR MINUS PLUS MULT DIV MOD
%token ASSIGN PLUSASSIGN MINUSASSIGN
%token EQ GT LT GTEQ LTEQ NEQ BING UNARY
%left EQ NEQ GT LT GTEQ LTEQ
%left AND OR
%left MINUS PLUS
%left MULT DIV MOD
%left BING
%left UNARY
%type <strVal> ID
%type <strVal> TYPES
%type <intVal> DEC_LITERAL
%type <intVal> HEX_LITERAL
%type <strVal> STRING_LITERAL
%type <strVal> ASSIGN
%type <strVal> PLUSASSIGN
%type <strVal> MINUSASSIGN
%type <strVal> CHAR_LITERAL
%type <strVal> BOOL_LITERAL
%type <strVal> MINUS
%type <strVal> BING
%type <strVal> MULT
%type <strVal> DIV
%type <strVal> PLUS
%type <strVal> MOD
%type <strVal> AND
%type <strVal> OR
%type <strVal> EQ
%type <strVal> NEQ
%type <strVal> GT
%type <strVal> LT
%type <strVal> GTEQ
%type <strVal> LTEQ
%type <prog> Program
%type <stmt> StatementDecl
%type <stmtlist> StatementDeclList
%type <symlist> VariableList
%type <sym> Variable
%type <intVal> Type
%type <intLit> IntegerLiteral
%type <strVal> AssignOp
%type <loc> Location
%type <expr> Expr
%type <binexpr> BinaryExpr
%type <carglist> CalloutArgList
%type <carg> CalloutArg
%type <method> MethodDecl
%type <methList> MethodDeclList
%type <methList> nonEmptyMethodDeclList
%type <meth1> MethodCall
%type <bl> Block
%type <param> ParameterDecl
%type <paramList> ParameterDeclList
%type <paramList> nonEmptyParameterDeclList
%type <exprList> ExprList
%type <exprList> nonEmptyExprList
%%
/* Grammar for the Decaf Programming Language */
Program: HEADER '{' FieldDeclList MethodDeclList '}' { $$ = new ASTProgramNode($4); root = $$; BuildIR(root); }
;
MethodDecl: Type ID '(' ParameterDeclList ')' Block { $$ = new ASTMethodDeclNode($1, *($2), $4, $6); }
| VOID ID '(' ParameterDeclList ')' Block { $$ = new ASTMethodDeclNode(3, *($2), $4, $6); }
;
MethodDeclList: /* empty */ { $$ = new list<ASTMethodDeclNode *>(); }
| nonEmptyMethodDeclList { $$ = $1; }
;
nonEmptyMethodDeclList: MethodDecl { $$ = new list<ASTMethodDeclNode *>(); $$->push_back($1); }
| nonEmptyMethodDeclList MethodDecl { $$ = $1; $$->push_back($2); }
;
FieldDeclList: /* empty */
| FieldDeclList FieldDecl
;
StatementDeclList: /* empty */ { $$ = new list<ASTStatementDeclNode *>(); }
| StatementDeclList StatementDecl { $$ = $1; $$->push_back($2); }
;
FieldDecl: Type VariableList ';' { annotateSymbolTable($1, $2); }
;
VariableList: Variable { $$ = new list<Symbol *>(); $$->push_back($1); }
| VariableList ',' Variable { $$ = $1; $$->push_back($3); }
;
Variable: ID { $$ = new Symbol(*($1)); }
| ID '[' IntegerLiteral ']' { $$ = new Symbol(*($1), $3); }
;
Type: TYPES { if(!($1->compare("int"))) $$ = _int_; else $$ = _bool_; }
;
IntegerLiteral: DEC_LITERAL { $$ = new ASTIntegerLiteralExpressionNode($1); }
| HEX_LITERAL { $$ = new ASTIntegerLiteralExpressionNode($1); }
;
StatementDecl: Location AssignOp Expr ';' { $$ = new ASTAssignmentStatementNode($1, *($2), $3); }
| MethodCall ';' { $$ = $1; }
| IF '(' Expr ')' Block { $$ = new ASTIfStatementDeclNode($3, $5, nullptr); }
| IF '(' Expr ')' Block ELSE Block { $$ = new ASTIfStatementDeclNode($3, $5, $7); }
| FOR ID AssignOp Expr ',' Expr Block { $$ = new ASTForStatementDeclNode(*($2), $4, $6, $7); }
| RETURN Expr ';' { $$ = new ASTReturnStatementNode($2); }
| BREAK ';' { $$ = new ASTBreakStatementNode(); }
| CONTINUE ';' { $$ = new ASTContinueStatementNode(); }
| Block { $$ = new ASTBlockStatementNode($1); }
;
MethodCall: ID '(' ExprList ')' { $$ = new ASTSimpleMethodCallNode(*($1), $3); }
| CALLOUT '(' STRING_LITERAL ',' CalloutArgList ')' { $$ = new ASTCalloutMethodCallNode(*($3), $5); }
;
ParameterDeclList: /* empty */ { $$ = new list<ASTParameterDecl *>(); }
| nonEmptyParameterDeclList { $$ = $1; }
;
nonEmptyParameterDeclList: ParameterDecl { $$ = new list<ASTParameterDecl *>(); $$->push_back($1); }
| nonEmptyParameterDeclList ',' ParameterDecl { $$ = $1; $$->push_back($3); }
;
ParameterDecl: Type ID { $$ = new ASTParameterDecl($1, *($2), false); }
| Type ID '[' ']' { $$ = new ASTParameterDecl($1, *($2), true); }
;
Block: '{' FieldDeclList StatementDeclList '}' { $$ = new ASTBlock($3); }
;
AssignOp: ASSIGN { $$ = $1; }
| PLUSASSIGN { $$ = $1; }
| MINUSASSIGN { $$ = $1; }
;
Location: ID { $$ = new ASTVarLocationNode(*($1)); }
| ID '[' Expr ']' { $$ = new ASTArrayLocationNode(*($1), $3); }
;
ExprList: /* empty */ { $$ = new list<ASTExpressionNode *>(); }
| nonEmptyExprList { $$ = $1; }
;
nonEmptyExprList: Expr { $$ = new list<ASTExpressionNode *>(); $$->push_back($1); }
| nonEmptyExprList ',' Expr { $$ = $1; $$->push_back($3); }
;
Expr: Location { $$ = new ASTLocationExpressionNode($1); }
| MethodCall { $$ = new ASTMethodCallExpressionNode($1); }
| IntegerLiteral { $$ = $1; }
| MINUS Expr %prec UNARY { $$ = new ASTUnaryExpressionNode($2, *($1)); }
| BING Expr { $$ = new ASTUnaryExpressionNode($2, *($1)); }
| CHAR_LITERAL { $$ = new ASTCharLiteralExpressionNode((*$1)[0]); }
| BOOL_LITERAL { $$ = new ASTBoolLiteralExpressionNode(*($1)); }
| '(' Expr ')' { $$ = $2; }
| BinaryExpr { $$ = $1; }
;
BinaryExpr: Expr MULT Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr DIV Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr PLUS Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr MINUS Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr MOD Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr AND Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr OR Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr EQ Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr NEQ Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr GT Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr LT Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr GTEQ Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
| Expr LTEQ Expr { $$ = new ASTBinaryExpressionNode($1, $3, *($2)); }
;
CalloutArgList: CalloutArg { $$ = new list<ASTCalloutArg *>(); $$->push_back($1); }
| CalloutArgList ',' CalloutArg { $$ = $1; $$->push_back($3); }
;
CalloutArg: Expr { $$ = new ASTExpressionCalloutArg($1); }
| STRING_LITERAL { $$ = new ASTStringCalloutArg(*$1); }
;
%%
int yyerror(string s)
{
extern int yylineno; // defined and maintained in lex.c
extern char *yytext; // defined and maintained in lex.c
cout << "ERROR: " << s << " at symbol \"" << yytext;
cout << "\" on line " << yylineno << endl;
exit(1);
}
int yyerror(char *s)
{
return yyerror(string(s));
}