This repository has been archived by the owner on Dec 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.y
538 lines (507 loc) · 11.2 KB
/
parser.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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
%{
#include"common.h"
#define YYSTYPE TreeNode*
TreeNode* root = new TreeNode(0, NODE_PROG);
extern int yylineno;
// max_scope_id 是堆栈下一层结点的最大编号
unsigned char max_scope_id = SCOPE_ID_BASE;
string presentScope = "0";
unsigned int top = 0;
TreeNode* nodePrint = new TreeNode(-1, NODE_VARDEC);
// multimap <标识符名称, 作用域> 变量名列表
extern multimap<string, string> idNameList = {
{"println_int", "0"}
};
// map <<标识符名称, 作用域>, 结点指针> 变量列表
extern map<pair<string, string>, TreeNode*> idList = {
{make_pair("println_int", "0"), nodePrint}
};
// 用于检查continue和break是否在循环内部
int inCycle = 0;
extern void InitIOFunctionNode();
int yylex ();
int yyerror(const char*);
int scopeCmp(string preScope, string varScope);
void scopePush();
void scopePop();
%}
%locations
// 关键字
%token RETURN INT VOID IF ELSE WHILE CONTINUE BREAK
// 标识符
%token ID
// 常量
%token INTEGER
// 赋值运算符
%token ASSIGN
// 一元运算符
%token NOT COMPL
// 二元运算符
%token ADD SUB MUL DIV MOD AND OR BAND BOR XOR EQ GE LE NE GT LT
// 括号分号逗号
%token SEMI COMMA LPAREN RPAREN LBRACE RBRACE
// 优先级
%left COMMA
%right ASSIGN
%left OR
%left AND
%left BOR
%left XOR
%left BAND
%left EQ NE
%left GT GE LT LE
%left ADD SUB
%left MUL DIV MOD
%right UNM NOT COMPL
%left LPAREN RPAREN LBRACE RBRACE
%start program
%%
/*
* High-Level Definitions
*/
/* 程序 */
program
: extDefList {root->addChild($1);}
;
/* 全局函数定义 */
extDefList
: %empty {$$ = new TreeNode(yylineno, NODE_EXTDEFL);}
| extDefList extDef {$$ = $1; $$->addChild($2);}
;
extDef
: specifier funcDec compSt {
$$ = new TreeNode(yylineno, NODE_EXTDEF);
$$->addChild($1);
$$->addChild($2);
$$->addChild($3);
} /* 返回类 函数头 函数体 */
;
/*
* Specifiers
*/
/* 类型描述符 */
specifier
: type {$$ = new TreeNode(yylineno, NODE_SPEC); $$->addChild($1);} /* 基本类型 */
;
type
: INT {$$ = new TreeNode(yylineno, NODE_TYPE); $$->type = TYPE_INT;}
| VOID {$$ = new TreeNode(yylineno, NODE_TYPE); $$->type = TYPE_VOID;}
;
/*
* Declarators
*/
/* 单变量声明 */
varDec
: ID {
$$ = new TreeNode(yylineno, NODE_VARDEC);
$$->var_name = $1->var_name;
$$->var_scope = presentScope;
#ifdef ID_REDUCE_DEBUG
cout<<"$ reduce declIdentifier : "<<$$->var_name<<", at scope :"<<presentScope<<endl;
#endif
if (idList.count(make_pair($$->var_name, $$->var_scope)) != 0) {
string t = "Redeclared identifier : " + $$->var_name;
yyerror(t.c_str());
}
idNameList.insert(make_pair($$->var_name, $$->var_scope));
idList[make_pair($$->var_name, $$->var_scope)] = $$;
}
;
/* 函数声明 */
funcDec
: varDec funcLP varList RPAREN {
$$ = new TreeNode(yylineno, NODE_FUNCDEC);
$$->addChild($1);
$$->addChild($3);
}
| varDec funcLP RPAREN {
$$ = new TreeNode(yylineno, NODE_FUNCDEC);
$$->addChild($1);
}
;
funcLP
: LPAREN {
scopePush();
}
;
/* 形参列表 */
varList
: paramDec {
$$ = new TreeNode(yylineno, NODE_VARLIST);
$$->addChild($1);
}
| varList COMMA paramDec {
$$ = $1;
$$->addChild($3);
}
;
/* 形参声明 */
paramDec
: specifier varDec {
$$ = new TreeNode(yylineno, NODE_PARAMDEC);
$$->addChild($1);
$$->addChild($2);
}
;
/*
* Statements
*/
/* 语句块 */
compSt
: LBRACE compList RBRACE {
$$ = new TreeNode(yylineno, NODE_COMPST);
$$->addChild($2);
scopePop();
}
;
compList
: %empty {
$$ = new TreeNode(yylineno, NODE_COMPL);
}
| compList defList stmtList {
$$ = $1;
$$->addChild($2);
$$->addChild($3);
}
;
/* 一系列语句 */
stmtList
: %empty {$$ = new TreeNode(yylineno, NODE_STMTL);}
| stmtList stmt {
$$ = $1;
$$->addChild($2);
}
;
/* 单个语句 */
stmt
: expr SEMI {
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_EXPR;
$$->addChild($1);
}
| RETURN expr SEMI {
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_RETURN;
$$->addChild($2);
} /* 返回语句 */
| compSt {
$$ = $1;
}
| if LPAREN expr RPAREN stmt {
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_IF;
$$->addChild($3);
$$->addChild($5);
}
| if LPAREN expr RPAREN stmt else stmt {
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_IF_ELSE;
$$->addChild($3);
$$->addChild($5);
$$->addChild($7);
}
| while LPAREN expr RPAREN stmt {
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_WHILE;
$$->addChild($3);
$$->addChild($5);
inCycle--;
}
| BREAK SEMI {
if(!inCycle) yyerror("break statement outside loop");
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_BREAK;
}
| CONTINUE SEMI {
if(!inCycle) yyerror("continue statement outside loop");
$$ = new TreeNode(yylineno, NODE_STMT);
$$->stype = STMT_CONTINUE;
}
;
if
: IF {scopePush();}
;
else
: ELSE {scopePush();}
;
while
: WHILE {inCycle++; scopePush();}
;
/*
* Local Definitions
*/
/* 一系列局部变量定义 */
defList
: %empty {$$ = new TreeNode(yylineno, NODE_DEFL);}
| defList def {
$$ = $1;
$$->addChild($2);
}
;
/* 局部变量定义 */
def
: specifier decList SEMI {
$$ = new TreeNode(yylineno, NODE_DEF);
$$->addChild($1);
$$->addChild($2);
}
;
/* 局部变量列表 */
decList
: dec {$$ = new TreeNode(yylineno, NODE_DECL); $$->addChild($1);}
| decList COMMA dec {
$$ = $1;
$$->addChild($3);
}
;
/* 单局部变量 */
dec
: varDec {$$ = new TreeNode(yylineno, NODE_DEC); $$->addChild($1);}
| varDec ASSIGN expr {
$$ = new TreeNode(yylineno, NODE_DEC);
$$->optype = OP_ASSIGN;
$$->addChild($1);
$$->addChild($3);
} /* 定义时初始化 */
;
/*
* Expressions
*/
expr
: expr ASSIGN expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_ASSIGN;
$$->addChild($1);
$$->addChild($3);
#ifdef ASSIGN_DEBUG
cerr << "$ reduce ASSIGN at scope : " << presentScope << ", at line " << lineno << endl;
#endif
}
| expr AND expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_AND;
$$->addChild($1);
$$->addChild($3);
}
| expr OR expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_OR;
$$->addChild($1);
$$->addChild($3);
}
| expr BAND expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_BAND;
$$->addChild($1);
$$->addChild($3);
}
| expr BOR expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_BOR;
$$->addChild($1);
$$->addChild($3);
}
| expr XOR expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_XOR;
$$->addChild($1);
$$->addChild($3);
}
| expr ADD expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_ADD;
$$->addChild($1);
$$->addChild($3);
}
| expr SUB expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_SUB;
$$->addChild($1);
$$->addChild($3);
}
| expr MUL expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_MUL;
$$->addChild($1);
$$->addChild($3);
}
| expr DIV expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_DIV;
$$->addChild($1);
$$->addChild($3);
}
| expr MOD expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_MOD;
$$->addChild($1);
$$->addChild($3);
}
| expr EQ expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_EQ;
$$->addChild($1);
$$->addChild($3);
}
| expr NE expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_NE;
$$->addChild($1);
$$->addChild($3);
}
| expr LE expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_LE;
$$->addChild($1);
$$->addChild($3);
}
| expr LT expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_LT;
$$->addChild($1);
$$->addChild($3);
}
| expr GE expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_GE;
$$->addChild($1);
$$->addChild($3);
}
| expr GT expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_BINARY;
$$->optype = OP_GT;
$$->addChild($1);
$$->addChild($3);
}
| LPAREN expr RPAREN {$$ = $2;}
| SUB expr %prec UNM {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_UNARY;
$$->optype = OP_UNM;
$$->addChild($2);
}
| NOT expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_UNARY;
$$->optype = OP_NOT;
$$->addChild($2);
}
| COMPL expr {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_UNARY;
$$->optype = OP_COMPL;
$$->addChild($2);
}
| ID LPAREN args RPAREN {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_FUNCALL;
$$->addChild($1);
$$->addChild($3);
#ifdef FUNCALL_DEBUG
cerr << "$ reduce function call at scope : " << presentScope << ", at line " << yylineno << endl;
#endif
} /* 带参数调用函数 */
| ID LPAREN RPAREN {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_FUNCALL;
$$->addChild($1);
#ifdef FUNCALL_DEBUG
cerr << "$ reduce function call at scope : " << presentScope << ", at line " << yylineno << endl;
#endif
} /* 无参数调用函数 */
| ID {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_ID;
$$->addChild($1);
}
| INTEGER {
$$ = new TreeNode(yylineno, NODE_EXPR);
$$->etype = EXPR_CONST;
$$->addChild($1);
}
;
args
: expr {
$$ = new TreeNode(yylineno, NODE_ARGS);
$$->addChild($1);
}
| args COMMA expr {
$$ = $1;
$$->addChild($3);
}
;
%%
int yyerror(const char* s)
{
PR("Parse error : %s at line %d\n", s, yylineno);
return -1;
}
/*
* 作用域比较函数 int scopeCmp (string, string)
*
* 输入参数:
* presScope: 当前变量所处的作用域
* varScope: 希望进行比较的已声明变量作用域
*
* 返回值:
* 0: 作用域相同,
* 若为变量声明语句,为变量重定义。
* >0: 已声明变量作用域在当前作用域外层,返回作用域距离(堆栈层数)
* 若为声明语句,不产生冲突,当前变量为新定义变量,
* 若为使用语句,当前变量为新定义变量。
* -1:已声明变量作用域在当前作用域内层,
* 若为声明语句,不可能出现这种情况,
* 若为使用语句,不产生冲突。
* -2:两个作用域互不包含,任何情况下都不会互相干扰
*/
int scopeCmp(string presScope, string varScope) {
unsigned int plen = presScope.length(), vlen = varScope.length();
unsigned int minlen = min(plen, vlen);
if (presScope.substr(0, minlen) == varScope.substr(0, minlen)) {
if (plen >= vlen)
return plen - vlen;
else
return -1;
}
return -2;
}
void scopePush() {
presentScope += max_scope_id;
max_scope_id = SCOPE_ID_BASE;
top++;
#ifdef SCOPE_DEBUG
PR("* push -> %s, at line %d\n", presentScope.c_str(), yylineno);
#endif
}
void scopePop() {
max_scope_id = presentScope[top] + 1;
presentScope = presentScope.substr(0, presentScope.length() - 1);
top--;
#ifdef SCOPE_DEBUG
PR("* pop -> %s, at line %d\n", presentScope.c_str(), yylineno);
#endif
}
void InitIOFunctionNode() {
nodePrint->var_name = "println_int";
nodePrint->var_scope = "0";
nodePrint->type = new Type(COMPOSE_FUNCTION);
nodePrint->type->retType = TYPE_VOID;
nodePrint->type->paramType[nodePrint->type->paramNum++] = TYPE_INT;
}