-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathparser.mly
More file actions
138 lines (122 loc) · 3.62 KB
/
parser.mly
File metadata and controls
138 lines (122 loc) · 3.62 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
138
%{
(* Put OCaml helper functions here *)
open Logoturtle
%}
%token <float> FLOAT
%token <string> ID
%token <string> PARAM
%token <bool> BOOL
%token PLUS
%token MINUS
%token TIMES
%token DIVIDE
%token OR
%token AND
%token NOT
%token LESS
%token GREATER
%token EQUAL
%token NOTEQUAL
%token LESSEQUAL
%token GREATEREQUAL
%token IF
%token STOP
%token TO
%token END
%token FORWARD
%token BACK
%token LEFT
%token RIGHT
%token REPEAT
%token REPCOUNT
%token SIN
%token COS
%token POWER
%token EXP
%token LN
%token RANDOM
%token LEFT_BRACKET
%token RIGHT_BRACKET
%token LEFT_PAREN
%token RIGHT_PAREN
%token EOF
%start <Logoturtle.command list> prog
(* the order of the following is important to define precedence *)
%nonassoc SIN COS POWER EXP LN RANDOM
%left OR
%left AND
%nonassoc NOT
%nonassoc EQUAL NOTEQUAL
%nonassoc LESS LESSEQUAL GREATER GREATEREQUAL
%left PLUS MINUS
%left TIMES DIVIDE
%%
prog:
| EOF { [] }
| cmds = command_list; EOF { cmds }
;
command_list: cmds = rev_command_list { List.rev cmds }
rev_command_list:
| c = command; { [c] }
| cmds = rev_command_list; single_cmd = command; { single_cmd :: cmds }
;
expr:
| b = base { b }
| a = arith { a }
| b = boolean { b }
| ap = app { ap }
base:
| REPCOUNT { Var "repcount" }
| p = PARAM { Var p }
| b = BOOL { Bool b }
| f = FLOAT { Number f }
| LEFT_PAREN; e = expr; RIGHT_PAREN { e }
;
arith:
| e1 = expr; PLUS; e2 = expr { Plus (e1, e2) }
| e1 = expr; MINUS; e2 = expr { Minus (e1, e2) }
| e1 = expr; TIMES; e2 = expr { Times (e1, e2) }
| e1 = expr; DIVIDE; e2 = expr { Divide (e1, e2) }
| LEFT_PAREN; MINUS; e = expr; RIGHT_PAREN { Negate e }
;
boolean:
| NOT; e = expr; { Not e }
| e1 = expr; LESS; e2 = expr { Less (e1, e2) }
| e1 = expr; GREATER; e2 = expr { Greater (e1, e2) }
| e1 = expr; LESSEQUAL; e2 = expr { LessEq (e1, e2) }
| e1 = expr; GREATEREQUAL; e2 = expr { GreaterEq (e1, e2) }
| e1 = expr; EQUAL; e2 = expr { Equal (e1, e2) }
| e1 = expr; NOTEQUAL; e2 = expr { NEqual (e1, e2) }
| e1 = expr; OR; e2 = expr { Or (e1, e2) }
| e1 = expr; AND; e2 = expr { And (e1, e2 ) }
;
app:
| SIN; e = expr { UnaryFunc ("sin", e) }
| COS; e = expr { UnaryFunc ("cos", e) }
| EXP; e = expr { UnaryFunc ("exp", e) }
| LN; e = expr { UnaryFunc ("ln", e) }
| RANDOM; e = expr { UnaryFunc ("random", e) }
| POWER; e1 = expr; e2 = expr { BinaryFunc ("power", e1, e2) }
command:
| STOP { Stop }
| FORWARD; e = expr { Forward e }
| BACK; e = expr { Back e }
| RIGHT; e = expr { Right e }
| LEFT; e = expr { Left e }
| REPEAT; e = expr; LEFT_BRACKET; cmds = command_fields; RIGHT_BRACKET { Repeat (e, cmds) }
| name = ID; args = args_list; { Call (name, args) }
| TO; name = ID; params = params_list; cmds = command_fields; END { Procdef (name, params, cmds) }
| IF; e = expr; LEFT_BRACKET; cmds = command_fields; RIGHT_BRACKET { If (e, cmds) }
;
command_fields: cmd = rev_command_fields { List.rev cmd };
rev_command_fields:
| (* empty *) { [] }
| cmds = rev_command_fields; c = command { c :: cmds }
args_list: args = rev_args_list { List.rev args }
rev_args_list:
| (* empty *) { [] }
| args = rev_args_list; e = expr { e :: args }
params_list: params = rev_params_list { List.rev params }
rev_params_list:
| (* empty *) { [] }
| params = rev_params_list; p = PARAM { p :: params }