-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.mly
126 lines (107 loc) · 3.13 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
/* Ocamlyacc parser for TPL */
%{
open Ast
%}
%token SEMI LPAREN RPAREN LBRACE RBRACE LBRACKET RBRACKET COMMA DOT
%token PLUS MINUS TIMES DIVIDE ASSIGN NOT
%token EQ NEQ LT LEQ GT GEQ TRUE FALSE AND OR
%token RETURN IF ELSE FOR WHILE INT BOOL VOID STRING FLOAT INTARRAY FLOATARRAY STRARRAY TABLE
%token <int> LITERAL
%token <string> STRLITERAL
%token <string> FLOATLITERAL
%token <string> ID
%token EOF
%nonassoc NOELSE
%nonassoc ELSE
%right ASSIGN
%left OR
%left AND
%left EQ NEQ
%left LT GT LEQ GEQ
%left PLUS MINUS
%left TIMES DIVIDE
%right NOT NEG
%start program
%type <Ast.program> program
%%
program:
decls EOF { $1 }
decls:
/* nothing */ { [], [] }
| decls vdecl { ($2 :: fst $1), snd $1 }
| decls fdecl { fst $1, ($2 :: snd $1) }
fdecl:
typ ID LPAREN formals_opt RPAREN LBRACE vdecl_list stmt_list RBRACE
{ { typ = $1;
fname = $2;
formals = $4;
locals = List.rev $7;
body = List.rev $8 } }
formals_opt:
/* nothing */ { [] }
| formal_list { List.rev $1 }
formal_list:
typ ID { [($1,$2)] }
| formal_list COMMA typ ID { ($3,$4) :: $1 }
typ:
INT { Int }
| BOOL { Bool }
| VOID { Void }
| FLOAT {Float}
| STRING {String}
| STRARRAY {Strarray}
| INTARRAY {Intarray}
| FLOATARRAY {Floatarray}
| TABLE {Table}
vdecl_list:
/* nothing */ { [] }
| vdecl_list vdecl { $2 :: $1 }
vdecl:
typ ID SEMI { ($1, $2) }
stmt_list:
/* nothing */ { [] }
| stmt_list stmt { $2 :: $1 }
stmt:
expr SEMI { Expr $1 }
| RETURN SEMI { Return Noexpr }
| RETURN expr SEMI { Return $2 }
| LBRACE stmt_list RBRACE { Block(List.rev $2) }
| IF LPAREN expr RPAREN stmt %prec NOELSE { If($3, $5, Block([])) }
| IF LPAREN expr RPAREN stmt ELSE stmt { If($3, $5, $7) }
| FOR LPAREN expr_opt SEMI expr SEMI expr_opt RPAREN stmt
{ For($3, $5, $7, $9) }
| WHILE LPAREN expr RPAREN stmt { While($3, $5) }
expr_opt:
/* nothing */ { Noexpr }
| expr { $1 }
expr:
ID LBRACKET LITERAL RBRACKET {IndexValue($1 , $3)}
| LITERAL { Literal($1) }
| STRLITERAL { Strliteral($1) }
| FLOATLITERAL { Floatliteral (float_of_string $1) }
| TRUE { BoolLit(true) }
| FALSE { BoolLit(false) }
| ID { Id($1) }
| expr PLUS expr { Binop($1, Add, $3) }
| expr MINUS expr { Binop($1, Sub, $3) }
| expr TIMES expr { Binop($1, Mult, $3) }
| expr DIVIDE expr { Binop($1, Div, $3) }
| expr EQ expr { Binop($1, Equal, $3) }
| expr NEQ expr { Binop($1, Neq, $3) }
| expr LT expr { Binop($1, Less, $3) }
| expr LEQ expr { Binop($1, Leq, $3) }
| expr GT expr { Binop($1, Greater, $3) }
| expr GEQ expr { Binop($1, Geq, $3) }
| expr AND expr { Binop($1, And, $3) }
| expr OR expr { Binop($1, Or, $3) }
| MINUS expr %prec NEG { Unop(Neg, $2) }
| NOT expr { Unop(Not, $2) }
| ID ASSIGN expr { Assign($1, $3) }
| ID LPAREN actuals_opt RPAREN { Call($1, $3) }
| LPAREN expr RPAREN { $2 }
actuals_opt:
/* nothing */ { [] }
| actuals_list { List.rev $1 }
actuals_list:
expr { [$1] }
| actuals_list COMMA expr { $3 :: $1 }