-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.mly
More file actions
204 lines (160 loc) · 6.78 KB
/
parser.mly
File metadata and controls
204 lines (160 loc) · 6.78 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
/* ppc/parser.mly */
%{
open Keiko
open Dict
open Tree
open Util
%}
%token <Dict.ident> IDENT
%token <Keiko.op> MULOP ADDOP RELOP
%token <int> NUMBER
%token <char> CHAR
%token <Keiko.symbol * int> STRING
/* punctuation */
%token SEMI DOT COLON LPAR RPAR COMMA SUB BUS
%token EQUAL MINUS ASSIGN VBAR ARROW
%token BADTOK IMPOSSIBLE
/* keywords */
%token ARRAY BEGIN CONST DO ELSE END IF OF
%token PROC RECORD RETURN THEN TO TYPE
%token VAR WHILE NOT POINTER NIL REG
%token REPEAT UNTIL FOR ELSIF CASE
/* operator priorities */
%left RELOP EQUAL
%left ADDOP MINUS
%left MULOP
%nonassoc NOT UMINUS
%type <Tree.program> program
%start program
%%
program :
block DOT { Prog ($1, ref []) } ;
block :
decl_list BEGIN stmts END { makeBlock ($1, $3) } ;
decl_list :
/* empty */ { [] }
| decl decl_list { $1 @ $2 } ;
decl :
CONST const_decls { $2 }
| VAR var_decls { $2 }
| proc_decl { [$1] }
| TYPE type_decls { [TypeDecl $2] } ;
const_decls :
const_decl { [$1] }
| const_decl const_decls { $1 :: $2 } ;
const_decl :
IDENT EQUAL expr SEMI { ConstDecl ($1, $3) } ;
type_decls :
type_decl { [$1] }
| type_decl type_decls { $1 :: $2 } ;
type_decl :
IDENT EQUAL typexpr SEMI { ($1, $3) } ;
var_decls :
var_decl { [$1] }
| var_decl var_decls { $1 :: $2 } ;
var_decl :
ident_list COLON reg typexpr SEMI { VarDecl ($3, $1, $4) } ;
reg :
/* empty */ { VarDef }
| REG { RegDef } ;
proc_decl :
proc_heading SEMI block SEMI { ProcDecl ($1, $3) } ;
proc_heading :
PROC name params return_type { Heading ($2, $3, $4) } ;
params :
LPAR RPAR { [] }
| LPAR formal_decls RPAR { $2 } ;
formal_decls :
formal_decl { [$1] }
| formal_decl SEMI formal_decls { $1 :: $3 } ;
formal_decl :
ident_list COLON typexpr { VarDecl (CParamDef, $1, $3) }
| VAR ident_list COLON typexpr { VarDecl (VParamDef, $2, $4) }
| proc_heading { PParamDecl $1 } ;
return_type :
/* empty */ { None }
| COLON typexpr { Some $2 } ;
stmts :
stmt_list { match $1 with [x] -> x
| xs -> makeStmt (Seq $1, 0) } ;
stmt_list :
stmt { [$1] }
| stmt SEMI stmt_list { $1 :: $3 } ;
stmt :
line stmt1 { makeStmt ($2, $1) }
| /* A trick to force the right line number */
IMPOSSIBLE { failwith "impossible" } ;
line :
/* empty */ { !Util.lineno } ;
stmt1 :
/* empty */ { Skip }
| variable ASSIGN expr { Assign ($1, $3) }
| name actuals { ProcCall ($1, $2) }
| RETURN expr_opt { Return $2 }
| IF expr THEN stmts elses END { IfStmt ($2, $4, $5) }
| WHILE expr DO stmts END { WhileStmt ($2, $4) }
| REPEAT stmts UNTIL expr { RepeatStmt ($2, $4) }
| FOR name ASSIGN expr TO expr DO stmts END
{ let v = makeExpr (Variable $2) in
ForStmt (v, $4, $6, $8) }
| CASE expr OF arms else_part END { CaseStmt ($2, $4, $5) } ;
elses :
/* empty */ { makeStmt (Skip, 0) }
| ELSE stmts { $2 }
| ELSIF line expr THEN stmts elses { makeStmt (IfStmt ($3, $5, $6), $2) } ;
arms :
arm { [$1] }
| arm VBAR arms { $1 :: $3 } ;
arm :
expr COLON stmts { ($1, $3) };
else_part :
/* empty */ { makeStmt (Skip, 0) }
| ELSE stmts { $2 } ;
ident_list :
IDENT { [$1] }
| IDENT COMMA ident_list { $1 :: $3 } ;
expr_opt :
/* empty */ { None }
| expr { Some $1 } ;
expr :
variable { $1 }
| NUMBER { makeExpr (Number $1) }
| STRING { let (lab, len) = $1 in
makeExpr (String (lab, len)) }
| CHAR { makeExpr (Char $1) }
| NIL { makeExpr Nil }
| name actuals { makeExpr (FuncCall ($1, $2)) }
| NOT expr { makeExpr (Monop (Not, $2)) }
| MINUS expr %prec UMINUS { makeExpr (Monop (Uminus, $2)) }
| expr MULOP expr { makeExpr (Binop ($2, $1, $3)) }
| expr ADDOP expr { makeExpr (Binop ($2, $1, $3)) }
| expr MINUS expr { makeExpr (Binop (Minus, $1, $3)) }
| expr RELOP expr { makeExpr (Binop ($2, $1, $3)) }
| expr EQUAL expr { makeExpr (Binop (Eq, $1, $3)) }
| LPAR expr RPAR { $2 } ;
actuals :
LPAR RPAR { [] }
| LPAR expr_list RPAR { $2 } ;
expr_list :
expr { [$1] }
| expr COMMA expr_list { $1 :: $3 } ;
variable :
name { makeExpr (Variable $1) }
| variable SUB expr BUS { makeExpr (Sub ($1, $3)) }
| variable DOT name { makeExpr (Select ($1, $3)) }
| variable ARROW { makeExpr (Deref $1) } ;
typexpr :
name { TypeName $1 }
| ARRAY expr OF typexpr { Array ($2, $4) }
| RECORD fields END { Record $2 }
| POINTER TO typexpr { Pointer $3 } ;
fields :
field_decl opt_semi { [$1] }
| field_decl SEMI fields { $1 :: $3 } ;
field_decl :
ident_list COLON typexpr { VarDecl (FieldDef, $1, $3) } ;
opt_semi :
SEMI { () }
| /* empty */ { () } ;
name :
IDENT { makeName ($1, !Util.lineno) } ;