-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgrammar.y
More file actions
444 lines (393 loc) · 12.1 KB
/
grammar.y
File metadata and controls
444 lines (393 loc) · 12.1 KB
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
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern FILE *yyin;
void yyerror(const char *s);
extern int yylex(void);
int ii = 0, itop = -1, istack[100];
int ww = 0, wtop = -1, wstack[100];
#define _BEG_IF {istack[++itop] = ++ii;}
#define _END_IF {itop--;}
#define _i (istack[itop])
#define _BEG_WHILE {wstack[++wtop] = ++ww;}
#define _END_WHILE {wtop--;}
#define _w (wstack[wtop])
struct var { // 函数内局部变量数据结构
char* content; //这个词具体是什么符号
int address; //当这个标识符是变量的时候,用来记录这个变量的地址信息
};
struct function_struct {
struct var var_list[100]; // 变量的最大数量100
struct var param_list[100]; // 形参的最大数量100,调用函数次数最多为100
int param_num;
int param_stack_address;
int var_num;
int var_stack_address;
char* func_name;
int have_return;
};
struct function_struct funcs[100];
int function_num = 0;
int var_address(char* s, struct function_struct* func) { // 如果存在变量就返回其定义过的地址
// 先在实参中寻找是否有相同的变量名,如果有就直接返回这个的地址,否则才去找局部变量
for (int i = 0; i < func->param_num; i++) {
if (strcmp(s, func->param_list[i].content) == 0) {
// 下面不直接返回,而是和最大参数地址相对8区补,进行对称的操作是为了巧妙实现倒车入栈
// 因为传入的参数是顺序的,所以我们只要反向对称取址即可实现同样的效果
return 8 + func->param_stack_address - func->param_list[i].address;
}
}
for (int i = 0; i < func->var_num; i++) {
if (strcmp(s, func->var_list[i].content) == 0) {
return func->var_list[i].address;
}
}
func->var_stack_address -= 4;
struct var new_var;
new_var.content = strdup(s);
new_var.address = func->var_stack_address;
func->var_list[func->var_num++] = new_var;
return func->var_stack_address;
}
void param_address(char* s, struct function_struct* func) { // 如果存在变量就返回其定义过的地址
for (int i = 0; i < func->param_num; i++) {
if (strcmp(s, func->param_list[i].content) == 0) {
return;
}
}
func->param_stack_address += 4;
struct var new_var;
new_var.content = strdup(s);
new_var.address = func->param_stack_address;
func->param_list[func->param_num++] = new_var;
}
struct function_struct* analysised_func;
struct function_struct* called_func;
%}
%union {
char *identifier;
int ival;
}
%token <identifier> VOID INT
%token CONTINUE BREAK RETURN IF ELSE WHILE
%token SEMICOLON COMMA LPAREN RPAREN LBRACE RBRACE
%token <identifier> IDENTIFIER
%token <ival> NUMBER
%right ASSIGN
%left OR // ||
%left AND // &&
%left BIT_OR // |
%left BIT_XOR // ^
%left BIT_AND // &
%left EQ NE // == !=
%left LT LE GT GE // < <= > >=
%left PLUS MINUS // + -
%left MUL DIV MOD // * / %
%left BIT_NOT NOT
%start translation_unit
%%
// 整个翻译单元定义
translation_unit:
/* empty */ {
printf(".intel_syntax noprefix\n");
printf(".global println_int\n");
printf(".data\n");
printf(".extern printf\n");
printf("format_str:\n");
printf(".asciz \"%%d\\n\"\n");
printf(".text\n");
// 预定义println_int函数
printf("\nprintln_int:\n");
printf("push ebp\nmov ebp, esp\nsub esp, 4\n");
printf("push DWORD PTR[ebp+8]\n");
printf("push offset format_str\n");
printf("call printf\n");
printf("add esp, 8\n");
printf("leave\n");
printf("ret\n");
struct function_struct nf;
nf.func_name = strdup("println_int");
nf.param_num = 1;
nf.param_stack_address = 4;
nf.var_num = 0;
nf.var_stack_address = 0;
nf.have_return = 0;
funcs[function_num] = nf;
function_num++;
}
| translation_unit function_defination
;
function_defination:
function_name LPAREN params RPAREN LBRACE statements RBRACE {
printf("leave\n");
printf("ret\n");
}
;
function_name:
INT IDENTIFIER {
printf("\n.global %s\n", $2);
printf("%s:\n", $2);
printf("push ebp\n");
printf("mov ebp, esp\n");
printf("sub esp, 100\n");
struct function_struct nf;
nf.func_name = strdup($2);
nf.param_num = 0;
nf.param_stack_address = 4;
nf.var_num = 0;
nf.var_stack_address = 0;
nf.have_return = 1;
funcs[function_num] = nf;
analysised_func = &funcs[function_num];
function_num++;
}
| VOID IDENTIFIER {
printf("\n.global %s\n", $2);
printf("%s:\n", $2);
printf("push ebp\n");
printf("mov ebp, esp\n");
printf("sub esp, 100\n");
struct function_struct nf;
nf.func_name = strdup($2);
nf.param_num = 0;
nf.param_stack_address = 4;
nf.var_num = 0;
nf.var_stack_address = 0;
nf.have_return = 0;
funcs[function_num] = nf;
analysised_func = &funcs[function_num];
function_num++;
}
;
// 函数调用
function_call:
IDENTIFIER LPAREN arguments RPAREN {
printf("call %s\n", $1);
for (int i = 0; i < function_num; i++) {
if (strcmp(funcs[i].func_name, $1) == 0) {
called_func = &funcs[i];
for (int i = 0; i < called_func->param_num; i++) {
printf("add esp, 4\n");
}
if (called_func->have_return) {
printf("push eax\n");
}
}
}
}
;
// 形参定义
params:
/* empty */
| INT IDENTIFIER { // 带类型的函数参数说明这里是在定义阶段
param_address($2, analysised_func);
}
| params COMMA INT IDENTIFIER {
param_address($4, analysised_func);
}
;
// 实参形式定义
arguments:
/* empty */
| argument_list
;
argument_list:
expression
| argument_list COMMA expression
;
// 语句定义
statements:
/* empty */
| statements statement
;
statement:
RETURN expression SEMICOLON
| assign SEMICOLON
| declaration SEMICOLON
| function_call SEMICOLON
| if_statement
| while_statement
| ContinueStmt SEMICOLON
| BreakStmt SEMICOLON
;
TestExpr:
LPAREN expression RPAREN
;
StmtsBlock:
LBRACE statements RBRACE
;
// if_else语句定义
if_statement:
T_IF LPAREN expression RPAREN Then LBRACE statements RBRACE EndThen EndIf
| T_IF LPAREN expression RPAREN Then LBRACE statements RBRACE EndThen ELSE LBRACE statement RBRACE EndIf
;
T_IF:
IF {
_BEG_IF; printf("._begIf_%d:\n", _i);
}
Then:
/* empty */ { printf("pop eax\ncmp eax, 0\nje ._elIf_%d\n", _i); }
;
EndThen:
/* empty */ { printf("jmp ._endIf_%d\n._elIf_%d:\n", _i, _i); }
;
EndIf:
/* empty */ { printf("._endIf_%d:\n\n", _i); _END_IF; }
;
// while语句定义
while_statement:
While TestExpr Do StmtsBlock EndWhile
;
While:
WHILE { _BEG_WHILE; printf("._begWhile_%d:\n", _w); }
;
Do:
/* empty */ { printf("pop eax\ncmp eax, 0\nje ._endWhile_%d\n", _w); }
;
EndWhile:
/* empty */ { printf("jmp ._begWhile_%d\n._endWhile_%d:\n\n", _w, _w); _END_WHILE; }
;
BreakStmt:
BREAK { printf("jmp ._endWhile_%d\n", _w); }
;
ContinueStmt:
CONTINUE { printf("jmp ._begWhile_%d\n", _w); }
;
// 变量赋值
assign:
IDENTIFIER ASSIGN expression {
printf("mov DWORD PTR[ebp%+d], eax\n", var_address($1, analysised_func));
}
;
// 变量定义
declaration:
INT assign
| INT IDENTIFIER {
printf("mov DWORD PTR[ebp%+d], 0\n", var_address($2, analysised_func)); // 默认初始化值为0
}
| declaration COMMA IDENTIFIER { //解析形式,a
printf("mov DWORD PTR[ebp%+d], 0\n", var_address($3, analysised_func)); // 默认初始化值为0
}
| declaration COMMA assign
;
// 表达式定义
expression:
// 3种终结符
NUMBER {
printf("mov eax, %d\npush eax\n", $1);
}
| function_call
| IDENTIFIER {
// 在函数名和变量名不重复的前提下,可以做到这一点,利用当前名称是否出现在函数名中判断是否是函数
printf("mov eax, DWORD PTR[ebp%+d]\npush eax\n", var_address($1, analysised_func));
}
// 3种单目运算符
|
MINUS expression %prec NOT {
printf("pop eax\nneg eax\npush eax\n");
} // unary minus
| NOT expression {
printf("pop eax\ntest eax, eax\nsetz al\nmovzx eax, al\npush eax\n");
}
| BIT_NOT expression {
printf("pop eax\nnot eax\npush eax\n");
}
// 双目运算符
| expression PLUS expression {
printf("pop ebx\npop eax\n");
printf("add eax, ebx\npush eax\n");
}
| expression MINUS expression {
printf("pop ebx\npop eax\n");
printf("sub eax, ebx\npush eax\n");
}
| expression MUL expression {
printf("pop ebx\npop eax\n");
printf("imul eax, ebx\npush eax\n");
}
| expression DIV expression {
printf("pop ebx\npop eax\n");
printf("cdq\nidiv ebx\npush eax\n");
}
| expression MOD expression {
printf("pop ebx\npop eax\n");
printf("cdq\nidiv ebx\nmov eax, edx\npush eax\n");
}
| expression LT expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsetl al\nmovzx eax, al\npush eax\n");
}
| expression LE expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsetle al\nmovzx eax, al\npush eax\n");
}
| expression GT expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsetg al\nmovzx eax, al\npush eax\n");
}
| expression GE expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsetge al\nmovzx eax, al\npush eax\n");
}
| expression EQ expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsete al\nmovzx eax, al\npush eax\n");
}
| expression NE expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, ebx\nsetne al\nmovzx eax, al\npush eax\n");
}
| expression AND expression {
printf("pop ebx\npop eax\n");
printf("cmp eax, 0\nsetne al\n");
printf("movzx eax, al\ncmp ebx, 0\n");
printf("setne bl\nmovzx ebx, bl\n");
printf("and eax, ebx\npush eax\n");
}
| expression OR expression {
printf("pop ebx\npop eax\n");
printf("test eax, eax\n");
printf("setne al\ncbw\n cwde\ntest ebx, ebx\n");
printf("setne bl\nor al, bl\npush eax\n");
}
| expression BIT_AND expression {
printf("pop ebx\npop eax\n");
printf("and eax, ebx\npush eax\n");
}
| expression BIT_OR expression {
printf("pop ebx\npop eax\n");
printf("or eax, ebx\npush eax\n");
}
| expression BIT_XOR expression {
printf("pop ebx\npop eax\n");
printf("xor eax, ebx\npush eax\n");
}
// 括号
| LPAREN expression RPAREN
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main(int argc, char **argv) {
if (argc != 2) {
// fprintf(stderr, "Usage: %s <input-file>\n", argv[0]);
return 1;
}
// 打开输入文件
yyin = fopen(argv[1], "r");
if (!yyin) {
perror("Error opening input file");
return 1;
}
// 调用解析器
if (yyparse() == 0) {
// 解析成功,生成汇编代码
fclose(yyin);
return 0;
} else {
fclose(yyin);
return 1;
}
}