-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.y
167 lines (132 loc) · 5.82 KB
/
parser.y
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
%using mini_lang
%using GardensPoint
%using System.Linq
%namespace GardensPoint
%output=Parser.cs
%{
private AstBuilder builder;
public Program Program { get; private set; }
%}
%union
{
public string str;
public int num;
public List<string> strings;
public PrimType prim_type;
public AbstractType any_type;
public INode node;
public List<INode> nodes;
public IEvaluable eval;
public IAssignable lval;
public List<IEvaluable> evals;
}
%token Program If Else While Read Write Return Break Continue Create
%token Assign Or And BitOr BitAnd Eq Neq Gt Gte Lt Lte Plus Minus Mult Div Not BitNot
%token LParen RParen LBrace RBrace LBracket RBracket Semicolon Comma
%token <prim_type> Type
%token <str> String Ident
%token <eval> LitInt LitDouble LitBool
%type <node> block statement if while oneliner write read break create
%type <nodes> declaration declarations statements
%type <lval> lvalue
%type <eval> value_0 op_1 op_2 op_3 op_4 op_5 op_6 evaluable
%type <evals> sizes indexing
%type <any_type> type
%type <strings> idents
%type <num> dims
%%
start: Program block { Program = new Program($2 as Block); } ;
block: LBrace { builder.PushScope(); }
declarations statements RBrace { $3.AddRange($4); $$ = new Block($3); builder.PopScope(); }
| LBrace error RBrace { yyerrok(); }
;
declarations: declarations declaration { $1.AddRange($2); $$ = $1; }
| { $$ = new List<INode>(); }
;
statements: statements statement { $1.Add($2); $$ = $1; }
| { $$ = new List<INode>(); }
;
declaration: type idents Ident Semicolon { $$ = $2.Append($3).Select(x => builder.CreateDeclaration(x, $1) as INode).ToList(); }
| error Semicolon { yyerrok(); $$ = new List<INode>(); }
;
type: Type { $$ = $1 as AbstractType; }
| Type LBracket dims RBracket { $$ = new ArrayType($1, $3); }
;
dims: dims Comma { $$ = $1 + 1; }
| { $$ = 1; }
;
idents: idents Ident Comma { $1.Add($2); $$ = $1; }
| { $$ = new List<string>(); }
;
statement: block
| while
| if
| oneliner Semicolon
| error Semicolon { yyerrok(); }
;
while: While LParen evaluable RParen { builder.PushLoop(); }
statement { $$ = new While($3, $6); builder.PopLoop(); }
;
if: If LParen evaluable RParen statement { $$ = new IfElse($3, $5); }
| If LParen evaluable RParen statement Else statement { $$ = new IfElse($3, $5, $7); }
;
oneliner: evaluable { $$ = new ExprStatement($1); } // discard created value
| write
| create
| read
| break
| Continue { $$ = builder.CreateContinue(); }
| Return { $$ = new Return(); }
;
read: Read lvalue { $$ = new Read($2); } ;
write: Write evaluable { $$ = new Write($2); }
| Write String { $$ = new WriteString($2); }
;
break: Break { $$ = builder.CreateBreak(new Constant("1", PrimType.Integer)); }
| Break LitInt { $$ = builder.CreateBreak($2 as Constant); }
;
create: Create Ident indexing { $$ = new ArrayCreation(new Indexing(builder.CreateIdentifier($2), $3)); } ;
indexing: LBracket sizes evaluable RBracket { $2.Add($3); $$ = $2; } ;
sizes: sizes evaluable Comma { $1.Add($2); $$ = $1; }
| { $$ = new List<IEvaluable>(); }
;
// Operators
lvalue: Ident { $$ = new Variable(builder.CreateIdentifier($1)); }
| Ident indexing { $$ = new Indexing(builder.CreateIdentifier($1), $2); }
;
value_0: lvalue { $$ = $1 as IEvaluable; }
| LitInt
| LitDouble
| LitBool ;
op_1: Minus op_1 { $$ = new UnaryOp(UnaryOp.OpType.IntNegate, $2); }
| BitNot op_1 { $$ = new UnaryOp(UnaryOp.OpType.BitwiseNot, $2); }
| Not op_1 { $$ = new UnaryOp(UnaryOp.OpType.LogicalNot, $2); }
| LParen Type RParen op_1 { $$ = new UnaryOp($2, $4); }
| LParen evaluable RParen { $$ = $2; }
| value_0 ;
op_2: op_2 BitAnd op_1 { $$ = new MathOp(MathOp.OpType.BitAnd, $1, $3); }
| op_2 BitOr op_1 { $$ = new MathOp(MathOp.OpType.BitOr, $1, $3); }
| op_1 ;
op_3: op_3 Mult op_2 { $$ = new MathOp(MathOp.OpType.Mult, $1, $3); }
| op_3 Div op_2 { $$ = new MathOp(MathOp.OpType.Div, $1, $3); }
| op_2 ;
op_4: op_4 Plus op_3 { $$ = new MathOp(MathOp.OpType.Add, $1, $3); }
| op_4 Minus op_3 { $$ = new MathOp(MathOp.OpType.Sub, $1, $3); }
| op_3 ;
op_5: op_5 Eq op_4 { $$ = new CompOp(CompOp.OpType.Eq, $1, $3); }
| op_5 Neq op_4 { $$ = new CompOp(CompOp.OpType.Neq, $1, $3); }
| op_5 Gt op_4 { $$ = new CompOp(CompOp.OpType.Gt, $1, $3); }
| op_5 Gte op_4 { $$ = new CompOp(CompOp.OpType.Gte, $1, $3); }
| op_5 Lt op_4 { $$ = new CompOp(CompOp.OpType.Lt, $1, $3); }
| op_5 Lte op_4 { $$ = new CompOp(CompOp.OpType.Lte, $1, $3); }
| op_4 ;
op_6: op_6 And op_5 { $$ = new LogicOp(LogicOp.OpType.And, $1, $3); }
| op_6 Or op_5 { $$ = new LogicOp(LogicOp.OpType.Or, $1, $3); }
| op_5 ;
evaluable: Ident Assign evaluable { $$ = new Assignment(new Variable(builder.CreateIdentifier($1)), $3); }
| Ident indexing Assign evaluable { $$ = new Assignment(new Indexing(builder.CreateIdentifier($1), $2), $4); }
| op_6 ;
%%
public Parser(Scanner scanner, AstBuilder builder) : base(scanner) {
this.builder = builder;
}