-
Notifications
You must be signed in to change notification settings - Fork 4
/
cish_parse.mly
143 lines (121 loc) · 3.56 KB
/
cish_parse.mly
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
%{
open Cish_ast
open Lexing
(* use this to get the line number for the n'th token *)
let rhs n =
let pos = Parsing.rhs_start_pos n in
pos.pos_lnum
let parse_error s =
let pos = Parsing.symbol_end_pos () in
let l = pos.pos_lnum in
print_string ("Cish error: line "^(string_of_int l)^": "^s^"\n")
%}
%start program stmt
/* nonterminals */
%type <Cish_ast.program> program
%type <Cish_ast.func list> functionlist
%type <Cish_ast.func> func
%type <Cish_ast.var list> idlist
%type <Cish_ast.var list> formals
%type <Cish_ast.stmt> stmt
%type <Cish_ast.stmt> stmtlist
%type <Cish_ast.exp> yexp
%type <Cish_ast.exp list> explist
%type <Cish_ast.exp> orexp
%type <Cish_ast.exp> andexp
%type <Cish_ast.exp> equalexp
%type <Cish_ast.exp> relnexp
%type <Cish_ast.exp> addexp
%type <Cish_ast.exp> mulexp
%type <Cish_ast.exp> unaryexp
%type <Cish_ast.exp> atomicexp
%type <Cish_ast.exp option> expopt
/* terminals */
%token SEMI LPAREN RPAREN LBRACE RBRACE
%token EQEQ NEQ LTE GTE LT GT EQ BANG
%token PLUS MINUS TIMES DIV AND OR
%token RETURN IF ELSE WHILE FOR
%token LET COMMA MALLOC
%token <int> INT
%token <string> ID
%token EOF
/* Start grammer rules*/
%%
program :
| functionlist { $1 }
functionlist :
func { [$1] }
| func program { $1::$2 }
func :
ID formals LBRACE stmtlist RBRACE { Fn{name=$1;args=$2;body=$4;pos=rhs 1} }
formals :
LPAREN RPAREN { [] }
| LPAREN idlist RPAREN { $2 }
idlist :
ID { [$1] }
| ID COMMA idlist { $1::$3 }
stmt :
SEMI { (skip, rhs 1) }
| yexp SEMI { (Exp $1, rhs 1) }
| RETURN yexp SEMI { (Return $2, rhs 1) }
| LBRACE stmtlist RBRACE { $2 }
| IF LPAREN yexp RPAREN stmt ELSE stmt { (If($3,$5,$7), rhs 1) }
| IF LPAREN yexp RPAREN stmt { (If($3,$5,(skip, rhs 5)), rhs 1) }
| WHILE LPAREN yexp RPAREN stmt { (While($3,$5), rhs 1) }
| FOR LPAREN expopt SEMI expopt SEMI expopt RPAREN stmt {
let e1 = match $3 with None -> (Int(0), rhs 3) | Some e -> e in
let e2 = match $5 with None -> (Int(1), rhs 5) | Some e -> e in
let e3 = match $7 with None -> (Int(0), rhs 7) | Some e -> e in
(For(e1,e2,e3,$9), rhs 1)
}
| LET ID EQ yexp SEMI stmt { (Let($2,$4,$6), rhs 1) }
stmtlist :
stmt { $1 }
| stmt stmtlist { (Seq($1,$2), rhs 1) }
expopt :
{ None }
| yexp { Some $1 }
yexp:
orexp { $1 }
| ID EQ yexp { (Assign($1,$3), rhs 1) }
| TIMES unaryexp EQ yexp { (Store($2,$4), rhs 1) }
explist :
yexp { [$1] }
| yexp COMMA explist { $1::$3 }
orexp :
andexp { $1 }
| orexp OR andexp { (Or($1,$3), rhs 1) }
andexp :
equalexp { $1 }
| andexp AND equalexp { (And($1,$3), rhs 1) }
equalexp :
relnexp { $1 }
| equalexp EQEQ relnexp { (Binop($1,Eq,$3), rhs 1) }
| equalexp NEQ relnexp { (Binop($1,Neq,$3), rhs 1) }
relnexp :
addexp { $1 }
| relnexp LT addexp { (Binop($1,Lt,$3), rhs 1) }
| relnexp GT addexp { (Binop($1,Gt,$3), rhs 1) }
| relnexp LTE addexp { (Binop($1,Lte,$3), rhs 1) }
| relnexp GTE addexp { (Binop($1,Gte,$3), rhs 1) }
addexp :
mulexp { $1 }
| addexp PLUS mulexp { (Binop($1,Plus,$3), rhs 1) }
| addexp MINUS mulexp { (Binop($1,Minus,$3), rhs 1) }
mulexp :
unaryexp { $1 }
| mulexp TIMES unaryexp { (Binop($1,Times,$3), rhs 1) }
| mulexp DIV unaryexp { (Binop($1,Div,$3), rhs 1) }
unaryexp :
atomicexp { $1 }
| PLUS unaryexp { $2 }
| MINUS unaryexp { (Binop((Int 0,rhs 1),Minus,$2), rhs 1) }
| BANG unaryexp { (Not $2, rhs 1) }
| TIMES unaryexp { (Load $2, rhs 1) }
atomicexp :
INT { (Int $1, rhs 1) }
| ID { (Var $1, rhs 1) }
| atomicexp LPAREN RPAREN { (Call($1,[]), rhs 1) }
| atomicexp LPAREN explist RPAREN { (Call($1,$3), rhs 1) }
| MALLOC LPAREN yexp RPAREN { (Malloc($3), rhs 1) }
| LPAREN yexp RPAREN { $2 }