forked from esumii/min-caml
-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.mly
173 lines (162 loc) · 3.54 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
%{
(* parserが利用する変数、関数、型などの定義 *)
open Syntax
let addtyp x = (x, Type.gentyp ())
%}
/* (* 字句を表すデータ型の定義 (caml2html: parser_token) *) */
%token <bool> BOOL
%token <int> INT
%token <float> FLOAT
%token NOT
%token MINUS
%token PLUS
%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 COMMA
%token ARRAY_CREATE
%token DOT
%token LESS_MINUS
%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
%nonassoc prec_tuple
%left COMMA
%left EQUAL LESS_GREATER LESS GREATER LESS_EQUAL GREATER_EQUAL
%left PLUS MINUS PLUS_DOT MINUS_DOT
%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 }
| NOT exp
%prec prec_app
{ Not($2) }
| MINUS exp
%prec prec_unary_minus
{ match $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 EQUAL exp
{ Eq($1, $3) }
| exp LESS_GREATER exp
{ Not(Eq($1, $3)) (* some float comparisons differ from OCaml for NaN; see: https://github.com/esumii/min-caml/issues/13#issuecomment-1147032750 *) }
| exp LESS exp
{ Not(LE($3, $1)) }
| exp GREATER exp
{ Not(LE($1, $3)) }
| 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) }
| 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
{ failwith
(Printf.sprintf "parse error near characters %d-%d"
(Parsing.symbol_start ())
(Parsing.symbol_end ())) }
fundef:
| IDENT formal_args EQUAL exp
{ { name = addtyp $1; args = $2; body = $4 } }
formal_args:
| IDENT formal_args
{ addtyp $1 :: $2 }
| IDENT
{ [addtyp $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] }