-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.mly
207 lines (194 loc) · 4.29 KB
/
parser.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
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
%{
(* parserが利用する変数、関数、型などの定義 *)
open Syntax
let addtyp x = (x, Type.gentyp ())
let get_pos () = let curr = Parsing.symbol_start_pos () in
(curr.Lexing.pos_lnum, curr.Lexing.pos_cnum - curr.Lexing.pos_bol) (* line * offset *)
let addpos expr_ = let pos = get_pos () in
ExprWithPos(expr_, pos)
let rec rm_outside_pos expr_ = match expr_ with
| ExprWithPos(a, p) -> rm_outside_pos a
| _ -> expr_
%}
/* (* 字句を表すデータ型の定義 (caml2html: parser_token) *) */
%token <bool> BOOL
%token <int> INT
%token <float> FLOAT
%token NOT
%token FUN
%token MINUS
%token PLUS
%token AST
%token SLASH
%token MINUS_DOT
%token PLUS_DOT
%token AST_DOT
%token SLASH_DOT
%token EQUAL
%token LESS_GREATER
%token LESS_EQUAL
%token GREATER_EQUAL
%token LESS
%token GREATER
%token IF
%token THEN
%token ELSE
%token <Id.t> IDENT
%token LET
%token IN
%token REC
%token GLOBAL
%token COMMA
%token ARRAY_CREATE
%token DOT
%token LESS_MINUS
%token MINUS_GREATER
%token SEMICOLON
%token LPAREN
%token RPAREN
%token EOF
/* (* 優先順位とassociativityの定義(低い方から高い方へ) (caml2html: parser_prior) *) */
%nonassoc IN
%right prec_let
%right SEMICOLON
%right prec_if
%right LESS_MINUS
%right MINUS_GREATER
%nonassoc prec_tuple
%left COMMA
%left EQUAL LESS_GREATER LESS GREATER LESS_EQUAL GREATER_EQUAL
%left PLUS MINUS PLUS_DOT MINUS_DOT
%left AST SLASH
%left AST_DOT SLASH_DOT
%right prec_unary_minus
%left prec_app
%left DOT
/* (* 開始記号の定義 *) */
%type <Syntax.t> exp
%start exp
%%
simple_exp: /* (* 括弧をつけなくても関数の引数になれる式 (caml2html: parser_simple) *) */
| LPAREN exp RPAREN
{ $2 }
| LPAREN RPAREN
{ Unit }
| BOOL
{ Bool($1) }
| INT
{ Int($1) }
| FLOAT
{ Float($1) }
| IDENT
{ Var($1) }
| simple_exp DOT LPAREN exp RPAREN
{ Get($1, $4) }
exp: /* (* 一般の式 (caml2html: parser_exp) *) */
| simple_exp
{ $1 }
| FUN vars MINUS_GREATER exp
{ Fun($2, $4) }
| NOT exp
%prec prec_app
{ Not($2) }
| MINUS exp
%prec prec_unary_minus
{ match rm_outside_pos($2) with
| Float(f) -> Float(-.f) (* -1.23などは型エラーではないので別扱い *)
| e -> Neg(e) }
| exp PLUS exp /* (* 足し算を構文解析するルール (caml2html: parser_add) *) */
{ Add($1, $3) }
| exp MINUS exp
{ Sub($1, $3) }
| exp AST exp
{ Mul($1, $3) }
| exp SLASH exp
{ Div($1, $3) }
| exp EQUAL exp
{ Eq($1, $3) }
| exp LESS_GREATER exp
{ NEq($1, $3) }
| exp LESS exp
{ LT($1, $3) }
| exp GREATER exp
{ LT($3, $1) }
| exp LESS_EQUAL exp
{ LE($1, $3) }
| exp GREATER_EQUAL exp
{ LE($3, $1) }
| IF exp THEN exp ELSE exp
%prec prec_if
{ If($2, $4, $6) }
| MINUS_DOT exp
%prec prec_unary_minus
{ FNeg($2) }
| exp PLUS_DOT exp
{ FAdd($1, $3) }
| exp MINUS_DOT exp
{ FSub($1, $3) }
| exp AST_DOT exp
{ FMul($1, $3) }
| exp SLASH_DOT exp
{ FDiv($1, $3) }
| LET IDENT EQUAL exp IN exp
%prec prec_let
{ Let(addtyp $2, $4, $6) }
| LET REC fundef IN exp
%prec prec_let
{ LetRec($3, $5) }
| LET GLOBAL IDENT EQUAL exp IN exp
%prec prec_let
{ LetGlobal(addtyp $3, $5, $7) }
| simple_exp actual_args
%prec prec_app
{ App($1, $2) }
| elems
%prec prec_tuple
{ Tuple($1) }
| LET LPAREN pat RPAREN EQUAL exp IN exp
{ LetTuple($3, $6, $8) }
| simple_exp DOT LPAREN exp RPAREN LESS_MINUS exp
{ Put($1, $4, $7) }
| exp SEMICOLON exp
{ Let((Id.gentmp Type.Unit, Type.Unit), $1, $3) }
| ARRAY_CREATE simple_exp simple_exp
%prec prec_app
{ Array($2, $3) }
| error
{
let pos = get_pos () in
failwith
(Printf.sprintf "parse error near characters %d-%d line %d, offset %d"
(Parsing.symbol_start ())
(Parsing.symbol_end ())
(fst pos)
(snd pos)) }
fundef:
| IDENT formal_args EQUAL exp
{ { name = addtyp $1; args = $2; body = $4 } }
formal_args:
| IDENT formal_args
{ addtyp $1 :: $2 }
| IDENT
{ [addtyp $1] }
vars:
| IDENT vars
{ Var($1) :: $2 }
| IDENT
{ [Var($1)] }
actual_args:
| actual_args simple_exp
%prec prec_app
{ $1 @ [$2] }
| simple_exp
%prec prec_app
{ [$1] }
elems:
| elems COMMA exp
{ $1 @ [$3] }
| exp COMMA exp
{ [$1; $3] }
pat:
| pat COMMA IDENT
{ $1 @ [addtyp $3] }
| IDENT COMMA IDENT
{ [addtyp $1; addtyp $3] }