-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAssignmentParser.fsp
More file actions
132 lines (109 loc) · 5.55 KB
/
AssignmentParser.fsp
File metadata and controls
132 lines (109 loc) · 5.55 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
// MADE BY: Kevin Moore s204462, Aryan Mirzazadeh s204489, Jakob Jacobsen s204502, Bjørn Laursen s204451
// Open the file that defines the type "expr" we shall use as AST
%{
open AssignmentTypesAST
%}
// Declare the tokens (terminal symbols)
%token <float> NUM
%token <string> VAR
%token TIMES DIV PLUS MINUS POW LPAR RPAR EOF
%token ASSIGN SEMICOLON SKIP LBRACKET RBRACKET IF FI DO OD ASSERTS OR AND EQ LE GR NOT TRUE FALSE
// NOTE: the actual formats of these tokens are defined in the lexer file
// as regular expressions
// Specify precedence and associativity of operators
// Precedence is given by the order (from low to high)
// COMMENTED OUT
// %left PLUS MINUS
// %left TIMES DIV
// %right POW
// We declare the initial non-terminal symbol
%start start
// We specify the return type of each of then non-terminal symbols
%type <command> start
%type <command> command
%type <guardedCommand> guardedCommand
%type <aExpr> aExpr0
%type <aExpr> aExpr1
%type <aExpr> aExpr2
%type <aExpr> aExpr3
%type <bExpr> bExpr0
%type <bExpr> bExpr1
%type <bExpr> bExpr2
%type <bExpr> bExpr3
// Grammar productions
%%
// The first production in "formal" notation is
// start -> expression
// here written:
start: command EOF { $1 }
// Note that we need to insert an End-Of-File (EOF)
// The code annotation { $1 } specifies that parsing with this production
// returns whatever parsing the expression returns: $1 is the result of parsing
// the first component of the production (i.e. expression)
// The productions for expressions are like in the grammar we saw in class
// written in the yacc format:
// C ::= x := a | A[a] := a | skip | C ; C | if GC fi | do GC od
// GC ::= b -> C | GC [] GC
// a ::= n | x | A[a] | a + a | a - a | a * a | a / a | - a | a ^ a | (a)
// b ::= true | false | b & b | b | b | b && b | b || b | !b
// | a = a | a != a | a > a | a >= a | a < a | a <= a | (b)
command:
| VAR ASSIGN aExpr0 SEMICOLON command { CommandSeq(AssignVarExpr($1, $3), $5) }
| VAR ASSIGN aExpr0 { AssignVarExpr($1, $3) }
| SKIP SEMICOLON command { CommandSeq(Skip, $3)}
| SKIP { Skip }
| VAR LBRACKET aExpr0 RBRACKET ASSIGN aExpr0 SEMICOLON command { CommandSeq(AssignArray($1, $3, $6), $8) }
| VAR LBRACKET aExpr0 RBRACKET ASSIGN aExpr0 { AssignArray($1, $3, $6) } // A[a] := a
| IF guardedCommand FI SEMICOLON command { CommandSeq(IfExpr($2), $5) }
| IF guardedCommand FI { IfExpr($2) }
| DO guardedCommand OD SEMICOLON command { CommandSeq(DoExpr($2), $5) }
| DO guardedCommand OD { DoExpr($2) }
guardedCommand:
| bExpr0 ASSERTS command LBRACKET RBRACKET guardedCommand { GCSequence(BoolGC($1, $3), $6) }
| bExpr0 ASSERTS command { BoolGC($1, $3) }
// Arithmetic Expressions (Priority 0 to 3 highest)
aExpr0:
| aExpr0 PLUS aExpr1 { PlusExpr($1,$3) }
| aExpr0 MINUS aExpr1 { MinusExpr($1,$3) }
| aExpr1 { $1 }
aExpr1:
| aExpr1 TIMES aExpr2 { TimesExpr($1,$3) }
| aExpr1 DIV aExpr2 { DivExpr($1,$3) }
| aExpr2 { $1 }
aExpr2:
| aExpr3 POW aExpr2 { PowExpr($1,$3) }
| aExpr3 { $1 }
aExpr3:
| PLUS aExpr3 { UPlusExpr($2) }
| MINUS aExpr3 { UMinusExpr($2) }
| NUM { Num($1) }
| VAR { Var($1) }
| VAR LBRACKET aExpr0 RBRACKET { ListAExpr($1,$3) }
| LPAR aExpr0 RPAR { $2 }
// Boolean Expressions (Priority 0 to 3 highest)
bExpr0:
| bExpr0 OR OR bExpr1 { SCOrExpr($1, $4) }
| bExpr0 OR bExpr1 { OrExpr($1, $3) }
| bExpr1 { $1 }
bExpr1:
| bExpr1 AND AND bExpr2 { SCAndExpr($1, $4) }
| bExpr1 AND bExpr2 { AndExpr($1, $3) }
| bExpr2 { $1 }
bExpr2:
| aExpr0 EQ aExpr0 { EqExpr($1, $3) }
| aExpr0 LE EQ aExpr0 { LeEqExpr($1, $4) }
| aExpr0 LE aExpr0 { LeExpr($1, $3) }
| aExpr0 GR EQ aExpr0 { GrEqExpr($1, $4) }
| aExpr0 GR aExpr0 { GrExpr($1, $3) }
| aExpr0 NOT EQ aExpr0 { NotEqExpr($1, $4) }
| bExpr3 { $1 }
bExpr3:
| NOT bExpr3 { NotExpr($2) }
| TRUE { BoolExpr(true) }
| FALSE { BoolExpr(false) }
| LPAR bExpr0 RPAR { $2 }
// Again, the code annotation specifies the result of parsing
// For example { TimesExpr($1,$3) } specifies that parsing with the production
// returns the value TimesExpr($1,$3), where $i is the result of parsing
// component i in the production (in this case the lhs and rhs operands)
%%