-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsyntax.y
241 lines (196 loc) · 7.37 KB
/
syntax.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
%locations
%error-verbose
%{
#include "node.h"
#include "cmm-symtab.h"
#include "lib.h"
#include "ast.h"
#include <stdio.h>
#define YYDEBUG 1
extern int yylineno;
/* Avoid some annoying warnings */
extern int yylex();
extern int yyerror(const char*);
int is_syn_error = 0;
Node prog;
%}
/* declared types */
%union {
Node nd;
int lineno;
struct {
int lineno;
const char *s;
} op;
}
%token <nd>
FLOAT
INT
ID
TYPE
CHAR
%token <op>
RELOP
PLUS MINUS STAR DIV
AND OR NOT
%token <lineno>
DOT
LB RB
LP RP
LC RC
FOR WHILE
STRUCT
RETURN
ASSIGNOP
SEMI COMMA
IF ELSE SUB_ELSE
%type <nd>
Program
ExtDef
ExtDefList
ExtDecList
ExtDec
Specifier
StructSpecifier
VarDec
FunDec
ParamDec
VarList
CompSt
StmtList
Stmt
DefList
DecList
Def
Dec
Exp
Args
/* Handle shift/reduce conflict of if-if-else */
%nonassoc SUB_ELSE /* a fake token used to define the precedence of a production */
%nonassoc ELSE /* use nonassoc to define precedence only */
/* Handle ambiguity according to Appendix A */
%right ASSIGNOP
%left OR
%left AND
%left RELOP
%left PLUS MINUS
%left STAR DIV
%right NOT
/* TODO
* NEG operation is denoted as MINUS token, but we cannot define MINUS's
* association again, so how to handle the association of NEG which shares
* the same token with MINUS?
*/
%left LP RP DOT LB RB
%%
/* nonterminal start */
/* High-level Definitions */
Program : ExtDefList { prog = create_tree(PROG_is_EXTDEF, $1->lineno, $1); }
;
ExtDefList : ExtDef ExtDefList { $1->sibling = $2; $$ = $1; }
| { $$ = NULL; }
;
ExtDef : Specifier ExtDecList SEMI { $$ = create_tree(EXTDEF_is_SPEC_EXTDEC, $1->lineno, $1, $2); }
| Specifier SEMI { $$ = create_tree(EXTDEF_is_SPEC, $1->lineno, $1); }
| Specifier FunDec CompSt { $$ = create_tree(EXTDEF_is_SPEC_FUNC_COMPST, $1->lineno, $1, $2, $3); }
;
ExtDecList : ExtDec
| ExtDec COMMA ExtDecList { $1->sibling = $3; $$ = $1; }
;
ExtDec : VarDec { $$ = create_tree(EXTDEC_is_VARDEC, $1->lineno, $1);}
| VarDec ASSIGNOP INT { $$ = create_tree(EXTDEC_is_VARDEC_INITIALIZATION, $1->lineno, $1, $3);}
/* Specifiers */
Specifier : TYPE { $$ = create_tree(SPEC_is_TYPE, $1->lineno, $1); }
| StructSpecifier { $$ = create_tree(SPEC_is_STRUCT, $1->lineno, $1); }
;
StructSpecifier : STRUCT ID LC DefList RC { $$ = create_tree(STRUCT_is_ID_DEF, $1, $2, $4); }
| STRUCT LC DefList RC { $$ = create_tree(STRUCT_is_DEF, $1, $3); }
| STRUCT ID { $$ = create_tree(STRUCT_is_ID, $1, $2); }
;
/* Declarators */
VarDec : ID { $$ = create_tree(VARDEC_is_ID, $1->lineno, $1); }
| VarDec LB INT RB { $$ = create_tree(VARDEC_is_VARDEC_SIZE, $1->lineno, $1, $3); }
;
FunDec : ID LP VarList RP { $$ = create_tree(FUNC_is_ID_VAR, $1->lineno, $1, $3); }
| ID LP RP { $$ = create_tree(FUNC_is_ID_VAR, $1->lineno, $1, NULL); }
;
ParamDec : Specifier VarDec { $$ = create_tree(VAR_is_SPEC_VARDEC, $1->lineno, $1, $2); }
;
VarList : ParamDec COMMA VarList { $1->sibling = $3; $$ = $1; }
| ParamDec
;
/* Statements */
CompSt : LC DefList StmtList RC { $$ = create_tree(COMPST_is_DEF_STMT, $1, $2, $3); }
;
StmtList : Stmt StmtList { $1->sibling = $2; $$ = $1; }
| { $$ = NULL; }
;
Stmt : Exp SEMI { $$ = create_tree(STMT_is_EXP, $1->lineno, $1); }
| CompSt { $$ = create_tree(STMT_is_COMPST, $1->lineno, $1); }
| RETURN Exp SEMI { $$ = create_tree(STMT_is_RETURN, $1, $2); }
| IF LP Exp RP Stmt %prec SUB_ELSE { $$ = create_tree(STMT_is_IF, $1, $3, $5); }
| IF LP Exp RP Stmt ELSE Stmt { $$ = create_tree(STMT_is_IF_ELSE, $1, $3, $5, $7); }
| WHILE LP Exp RP Stmt { $$ = create_tree(STMT_is_WHILE, $1, $3, $5); }
| FOR LP Exp SEMI Exp SEMI Exp RP Stmt { $$ = create_tree(STMT_is_FOR, $1, $3, $5, $7, $9); }
;
/* Local Definitions */
DefList : Def DefList { $1->sibling = $2; $$ = $1; }
| { $$ = NULL; }
;
Def : Specifier DecList SEMI { $$ = create_tree(DEF_is_SPEC_DEC, $1->lineno, $1, $2); }
;
DecList : Dec
| Dec COMMA DecList { $1->sibling = $3; $$ = $1; }
;
Dec : VarDec { $$ = create_tree(DEC_is_VARDEC, $1->lineno, $1); }
| VarDec ASSIGNOP Exp { $$ = create_tree(DEC_is_VARDEC_INITIALIZATION, $1->lineno, $1, $3); }
;
/* Expressions */
Exp : Exp ASSIGNOP Exp { $$ = create_tree(EXP_is_ASSIGN, $2, $1, $3); }
| Exp AND Exp { $$ = create_tree(EXP_is_AND, $2.lineno, $1, $3); }
| Exp OR Exp { $$ = create_tree(EXP_is_OR, $2.lineno, $1, $3); }
| Exp RELOP Exp { $$ = create_tree(EXP_is_RELOP, $2.lineno, $1, $3); $$->val.operator = $2.s; }
| Exp PLUS Exp { $$ = create_tree(EXP_is_BINARY, $2.lineno, $1, $3); $$->val.operator = $2.s; }
| Exp MINUS Exp { $$ = create_tree(EXP_is_BINARY, $2.lineno, $1, $3); $$->val.operator = $2.s; }
| Exp STAR Exp { $$ = create_tree(EXP_is_BINARY, $2.lineno, $1, $3); $$->val.operator = $2.s; }
| Exp DIV Exp { $$ = create_tree(EXP_is_BINARY, $2.lineno, $1, $3); $$->val.operator = $2.s; }
| Exp LB Exp RB { $$ = create_tree(EXP_is_EXP_IDX, $2, $1, $3); }
| Exp DOT ID { $$ = create_tree(EXP_is_EXP_FIELD, $2, $1, $3); }
| LP Exp RP { $$ = $2; }
| MINUS Exp { $$ = create_tree(EXP_is_UNARY, $1.lineno, $2); $$->val.operator = $1.s;}
| NOT Exp { $$ = create_tree(EXP_is_UNARY, $1.lineno, $2); $$->val.operator = $1.s;}
| ID LP Args RP { $$ = create_tree(EXP_is_ID_ARG, $1->lineno, $1, $3); }
| ID LP RP { $$ = create_tree(EXP_is_ID_ARG, $1->lineno, $1, NULL); }
| ID { $$ = create_tree(EXP_is_ID, $1->lineno, $1); }
| INT { $$ = create_tree(EXP_is_INT, $1->lineno, $1); }
| FLOAT { $$ = create_tree(EXP_is_FLOAT, $1->lineno, $1); }
| CHAR { $$ = create_tree(EXP_is_CHAR, $1->lineno, $1); }
;
Args : Exp COMMA Args { $1->sibling = $3; $$ = $1; }
| Exp
;
/* nonterminal end */
%%
//
// Analyze the parsing tree
//
void semantic_analysis()
{
analyze_program(prog);
}
//
// Release the parsing tree
//
void free_ast()
{
free_node(prog);
}
//
// oeverride of yyerror
//
int yyerror(const char *msg)
{
is_syn_error = 1;
printf("Error type B at line %d: %s.\n", yylineno, msg);
return 0;
}