-
Notifications
You must be signed in to change notification settings - Fork 0
/
objlangparser.mly
132 lines (108 loc) · 2.98 KB
/
objlangparser.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
%{
open Lexing
open Objlang
open Error_syntax
let classes = ref []
let globals = ref []
let functions = ref []
%}
%token PLUS STAR
%token LT
%token <int> CST
%token <bool> BOOL
%token <string> IDENT
%token TYP_INT TYP_BOOL TYP_VOID
%token VAR FUNCTION
%token ATTRIBUTE METHOD EXTENDS CLASS THIS
%token DOT NEW LBRACKET RBRACKET
%token LPAR RPAR BEGIN END COMMA SEMI
%token PUTCHAR SET IF ELSE WHILE RETURN
%token EOF
%left LT
%left PLUS
%left STAR
%nonassoc LBRACKET DOT
%start program
%type <unit Objlang.program> program
%%
program:
| list(decl) EOF
{ {classes = List.rev !classes;
functions = List.rev !functions;
globals = List.rev !globals} }
| error { let pos = $startpos in
let p = make_position pos
in
raise (SyntaxError p) }
;
decl:
| c=class_def { classes := c :: !classes }
| v=variable_decl { let id, ty = v in globals := (id, ty) :: !globals }
| f=function_def { functions := f :: !functions }
;
class_def:
| CLASS name=IDENT parent=option(EXTENDS p=IDENT { p })
BEGIN fields=list(attribute_decl) methods=list(method_def) END
{ { name; fields; methods; parent; } }
;
variable_decl:
| VAR tid=typed_ident SEMI { tid }
;
attribute_decl:
| ATTRIBUTE tid=typed_ident SEMI { tid }
;
typed_ident:
| ty=typ id=IDENT { id, ty }
;
typ:
| TYP_INT { TInt }
| TYP_BOOL { TBool }
| TYP_VOID { TVoid }
| LBRACKET ty=typ RBRACKET { TArray ty }
| id=IDENT { TClass id }
;
function_def:
| FUNCTION fdef=fun_def { fdef }
;
method_def:
| METHOD mdef=fun_def { mdef }
;
fun_def:
| return=typ name=IDENT LPAR params=separated_list(COMMA, typed_ident) RPAR
BEGIN locals=list(variable_decl) code=list(instruction) END
{ {name; code; params; return; locals} }
;
instruction:
| PUTCHAR LPAR e=expression RPAR SEMI { Putchar(e) }
| id=IDENT SET e=expression SEMI { Set(id, e) }
| IF LPAR c=expression RPAR
BEGIN s1=list(instruction) END
ELSE BEGIN s2=list(instruction) END { If(c, s1, s2) }
| WHILE LPAR c=expression RPAR
BEGIN s=list(instruction) END { While(c, s) }
| RETURN e=expression SEMI { Return(e) }
| e=expression SEMI { Expr(e) }
| m=mem_access SET e=expression SEMI { Write(m, e) }
;
mem_access:
| e1=expression LBRACKET e2=expression RBRACKET { Arr(e1, e2) }
| e=expression DOT id=IDENT { Atr(e, id) }
;
expression:
| n=CST { mk_expr () (Cst n) }
| b=BOOL { mk_expr () (Bool b) }
| id=IDENT { mk_expr () (Var id) }
| LPAR e=expression RPAR { e }
| e1=expression op=binop e2=expression { mk_expr () (Binop(op, e1, e2)) }
| f=IDENT LPAR params=separated_list(COMMA, expression) RPAR { mk_expr () (Call(f, params)) }
| e=expression DOT f=IDENT LPAR params=separated_list(COMMA, expression) RPAR { mk_expr () (MCall(e, f, params)) }
| NEW id=IDENT LPAR params=separated_list(COMMA, expression) RPAR { mk_expr () (New(id, params)) }
| NEW LBRACKET ty=typ COMMA e=expression RBRACKET { mk_expr () (NewTab(ty, e)) }
| m=mem_access { mk_expr () (Read m) }
| THIS { mk_expr () (This) }
;
%inline binop:
| PLUS { Add }
| STAR { Mul }
| LT { Lt }
;