-
Notifications
You must be signed in to change notification settings - Fork 0
/
grammar.pegjs
105 lines (80 loc) · 2.71 KB
/
grammar.pegjs
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
{
const { parserOptions } = options;
const {
allowGoto,
allowIf,
allowLoop,
allowStop,
allowWhile,
ifStyle
} = parserOptions;
}
Start
= _ program:Program _ { return { program }; }
Program
= stmt:Statement stmts:(_ ';' _ otherStmt:Statement { return otherStmt; })*
{ return [stmt, ...stmts]; }
Statement
= stmt:StatementWithoutLabel { return stmt; }
/ label:Label _ stmt:StatementWithoutLabel { return { label, ...stmt }; }
Label
= &{return allowGoto;} id:Identifier _ ':' { return id; }
StatementWithoutLabel
= stmt:StatementInner
{ return { location: location(), ...stmt }; }
StatementInner
= assignment:Assignment { return assignment; }
/ &{return allowLoop;} loop:Loop { return loop; }
/ &{return allowWhile;} whileStmt:While { return whileStmt; }
/ &{return allowIf;} ifStmt:IfStatement { return ifStmt; }
/ &{return allowGoto;} gotoStmt:GotoStatement { return gotoStmt; }
/ &{return allowStop;} stopStmt:StopStatement { return stopStmt; }
Assignment
= id:Identifier _ ':=' _ value:IntExpression
{ return { type: 'assignment', id, value }; }
IntExpression
= arith:Arithmetic { return arith; }
/ atomic:Atomic { return atomic; }
Arithmetic
= left:Atomic _ op:Operator _ right:Atomic
{ return { type: 'arith', left, op, right }; }
Operator
= '+' / '-' / '*' / 'DIV' / 'MOD'
Loop
= 'LOOP' __ count:Atomic __ 'DO' __ body:Program __ 'END'
{ return { type: 'loop', count, body }; }
While
= 'WHILE' __ condition:BoolExpr __ 'DO' __ body:Program __ 'END'
{ return { type: 'while', condition, body }; }
IfStatement
= &{return ifStyle !== 'goto'} stmt:RegularIfThenStatement
{ return stmt; }
/ &{return ifStyle === 'goto'} stmt:IfThenGotoStatement
{ return stmt; }
RegularIfThenStatement
= 'IF' __ condition:BoolExpr __ 'THEN' __ thenPart:Program __ elsePart:('ELSE' __ p:Program __ { return p; })? 'END'
{ return { type: 'if', condition, thenPart, elsePart }; }
IfThenGotoStatement
= 'IF' __ condition:BoolExpr __ 'THEN' __ &GotoStatement stmt:Statement
{ return { type: 'if', condition, thenPart: [stmt] }}
GotoStatement
= 'GOTO' __ id:Identifier { return { type: 'goto', targetLabel: id }; }
StopStatement
= ('STOP' / 'HALT') { return { type: 'stop' }; }
BoolExpr
= left:Atomic _ op:BoolOp _ right:Atomic { return { left, op, right }; }
BoolOp
= '=' / '!=' / '<>' / '<=' / '<' / '>=' / '>'
Atomic
= value:Integer { return { type: 'constant', value }; }
/ id:Identifier { return { type: 'id', id }; }
Identifier
= [a-zA-Z][a-zA-Z0-9]* { return text(); }
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= ([ \t\n\r] / Comment)*
__
= ([ \t\n\r] / Comment)+
Comment
= '//' [^\n]* '\n'