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
|
%{
#include <stdio.h>
#include "ast.h"
extern char *yytext;
extern int yylineno;
extern int yylex();
ASTNode *ast_root;
void yyerror(const char *s) {
fprintf(stderr, "Parse error at token \"%s\", line %d: %s\n", yytext, yylineno, s);
}
%}
%union {
int num;
char *id;
struct ASTNode *node;
struct ASTNodeList *node_list;
}
%start prog
%token <num> T_NUM
%token <id> T_ID
%token T_EQ T_NE T_LT T_LE T_GT T_GE
%token T_TRUE T_FALSE
%left T_OR
%left T_AND
%token T_NOT
%left T_PLUS T_MINUS
%left T_STAR
%right T_UMINUS
%token T_SKIP T_END T_IF T_THEN T_ELSE T_WHILE T_DO T_VAR T_IN T_PROC T_BEGIN
%token T_ASSIGN
%token T_LPAREN T_RPAREN T_COM T_SEM
%type <node> prog stm var aexp bexp procd procc
%type <node_list> args
%%
prog : stm
{ ast_root = $1; }
;
stm : T_SKIP
{ $$ = ast_skip(); }
| var T_ASSIGN aexp
{ $$ = ast_assign($1, $3); }
| T_LPAREN stm T_SEM stm T_RPAREN
{ $$ = ast_seq($2, $4); }
| stm T_SEM stm
{ $$ = ast_seq($1, $3); }
| stm T_SEM
{ $$ = $1; }
| T_IF bexp T_THEN stm T_ELSE stm T_END
{ $$ = ast_if($2, $4, $6); }
| T_IF bexp T_THEN stm T_END
{ $$ = ast_if($2, $4, ast_skip()); }
| T_WHILE bexp T_DO stm T_END
{ $$ = ast_while($2, $4); }
| T_VAR var T_ASSIGN aexp T_IN stm T_END
{ $$ = ast_let($2, $4, $6); }
| procd
{ $$ = $1; }
| procc
{ $$ = $1; }
;
var : T_ID
{ $$ = ast_var($1); }
;
aexp : aexp T_PLUS aexp
{ $$ = ast_aop(AOP_ADD, $1, $3); }
| aexp T_MINUS aexp
{ $$ = ast_aop(AOP_SUB, $1, $3); }
| aexp T_STAR aexp
{ $$ = ast_aop(AOP_MUL, $1, $3); }
| T_MINUS aexp %prec T_UMINUS
{ $$ = ast_aop(AOP_SUB, ast_int(0), $2); }
| T_LPAREN aexp T_RPAREN
{ $$ = $2; }
| var
{ $$ = $1; }
| T_NUM
{ $$ = ast_int($1); }
;
bexp : bexp T_OR bexp
{ $$ = ast_bop(BOP_OR, $1, $3); }
| bexp T_AND bexp
{ $$ = ast_bop(BOP_AND, $1, $3); }
| T_NOT bexp
{ $$ = ast_not($2); }
| aexp T_EQ aexp
{ $$ = ast_rop(ROP_EQ, $1, $3); }
| aexp T_NE aexp
{ $$ = ast_rop(ROP_NE, $1, $3); }
| aexp T_LE aexp
{ $$ = ast_rop(ROP_LE, $1, $3); }
| aexp T_LT aexp
{ $$ = ast_rop(ROP_LT, $1, $3); }
| aexp T_GE aexp
{ $$ = ast_rop(ROP_GE, $1, $3); }
| aexp T_GT aexp
{ $$ = ast_rop(ROP_GT, $1, $3); }
| T_LPAREN bexp T_RPAREN
{ $$ = $2; }
| T_TRUE
{ $$ = ast_rop(ROP_EQ, ast_int(1), ast_int(1)); }
| T_FALSE
{ $$ = ast_rop(ROP_EQ, ast_int(0), ast_int(1)); }
;
args : var
{ $$ = ast_node_list($1, NULL); }
| args T_COM var
{ $$ = ast_node_list($3, $1); }
;
procd : T_PROC T_ID T_LPAREN args T_SEM args T_RPAREN T_BEGIN stm T_END
{ $$ = ast_procdecl($2, $4, $6, $9); }
;
procc : T_ID T_LPAREN args T_SEM args T_RPAREN
{ $$ = ast_proccall($1, $3, $5); }
;
%%
|