-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.mly
More file actions
137 lines (123 loc) · 3.23 KB
/
parser.mly
File metadata and controls
137 lines (123 loc) · 3.23 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
%{
(* 補助的な変数、関数、型などの定義 *)
open Syntax
(* 目的:変数列と本体の式から、入れ子になった1引数関数を作る *)
(* create_fun : string list -> Syntax.t -> Syntax.t *)
let create_fun variables expr =
List.fold_right (fun var expr -> Fun (var, expr)) variables expr
(* 目的:式の列から、Cons を使ったリストを作る *)
(* create_list : Syntax.t list -> Syntax.t *)
let create_list exprs =
List.fold_right (fun expr lst -> Cons (expr, lst)) exprs Nil
%}
/* 以降、どういうわけかコメントが C 式になることに注意 */
/* トークンの定義 */
%token <int> NUMBER
/* これは、数字には int 型の値が伴うことを示している */
%token <string> VAR
%token PLUS MINUS TIMES DIV
%token TRUE FALSE
%token EQUAL LESS GREATER
%token LPAREN RPAREN
%token IF THEN ELSE
%token LET REC IN
%token FUN ARROW
%token LBRACKET RBRACKET CONS SEMI
%token MATCH WITH BAR
%token RAISE ERROR TRY
%token EOF
/* End of File: 入力の終わりを示す */
/* 非終端記号の型をここで宣言する */
%type <Syntax.t> start
/* 開始記号の定義 */
%start start
/* 演算子の優先順位を指定する */
/* 下に行くほど強く結合する */
%nonassoc IN
%nonassoc THEN
%nonassoc ELSE
%nonassoc ARROW
%nonassoc EQUAL LESS GREATER
%right CONS
%left PLUS MINUS
%left TIMES DIV
%nonassoc UNARY
/* nonassoc は結合なし(毎回、かっこを書かなくてはならない)、
left は左結合、right は右結合 */
/* 以下の %% は省略不可。それ以降に文法規則を書く */
%%
start:
| expr EOF
{ $1 }
simple_expr:
| NUMBER
{ Number ($1) }
| VAR
{ Var ($1) }
| TRUE
{ Bool (true) }
| FALSE
{ Bool (false) }
| LPAREN expr RPAREN
{ $2 }
| LBRACKET RBRACKET
{ Nil }
| LBRACKET expr_semi_list RBRACKET
{ create_list $2 }
expr:
| simple_expr
{ $1 }
| expr PLUS expr
{ Op ($1, Plus, $3) }
| expr MINUS expr
{ Op ($1, Minus, $3) }
| expr TIMES expr
{ Op ($1, Times, $3) }
| expr DIV expr
{ Op ($1, Div, $3) }
| expr EQUAL expr
{ Op ($1, Equal, $3) }
| expr LESS expr
{ Op ($1, Less, $3) }
| expr GREATER expr
{ Op ($3, Less, $1) }
| MINUS expr %prec UNARY
{ Op (Number (0), Minus, $2) }
| IF expr THEN expr ELSE expr
{ If ($2, $4, $6) }
| LET VAR EQUAL expr IN expr
{ Let ($2, $4, $6) }
| LET REC VAR VAR EQUAL expr IN expr
{ Letrec ($3, $4, $6, $8) }
| LET REC VAR VAR variables EQUAL expr IN expr
{ Letrec ($3, $4, (create_fun $5 $7), $9) }
| FUN variables ARROW expr
{ create_fun $2 $4 }
| app
{ $1 }
| expr CONS expr
{ Cons ($1, $3) }
| MATCH expr WITH LBRACKET RBRACKET ARROW expr BAR VAR CONS VAR ARROW expr
{ Match ($2, $7, $9, $11, $13) }
| RAISE LPAREN ERROR expr RPAREN
{ Raise ($4) }
| TRY expr WITH ERROR VAR ARROW expr
{ Try ($2, $5, $7) }
variables:
| VAR
{ [$1] }
| VAR variables
{ $1 :: $2 }
app:
| simple_expr simple_expr
{ App ($1, $2) }
| app simple_expr
{ App ($1, $2) }
expr_semi_list:
| expr opt_semi
{ [$1] }
| expr SEMI expr_semi_list
{ $1 :: $3 }
opt_semi:
| { () }
| SEMI { () }