-
Notifications
You must be signed in to change notification settings - Fork 1
/
grammar.peg
84 lines (61 loc) · 2.95 KB
/
grammar.peg
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
start = l:line*
line = l:line_number space s:statement space ';' [\n\r]+
{ return l + '::' + s }
statement = add
/ put
/ print
/ double_compound
/ compound
add = a1:add_clause space ',' space a2:add { return a1 + ' ' + a2; }
/ add_clause
add_clause = l:integer '#' e:expression_integer { if (l < 0) { l = -l; e = '-(' + e + ')'; } return 'add(' + l + ', ' + e + ');' }
/ l:integer { let e = 1; if (l < 0) { l = -l; e = -e; } return 'add(' + l + ', ' + e + ');' }
line_number = positive_integer
double_compound =
'again' space '(' space e1:expression_bool space ')' space 'defer' space '(' space e2:expression_bool space ')' space s:(add / print / put)
{ return 'again_defer(' + e1 + ', ' + e2 + ', function () { ' + s + ' });' }
/ 'defer' space '(' space e2:expression_bool space ')' space 'again' space '(' space e1:expression_bool space ')' space s:(add / print / put)
{ return 'again_defer(' + e1 + ', ' + e2 + ', function () { ' + s + ' });' }
compound = c:('defer' / 'again') space '(' space e:expression_bool space ')' space s:(add / print / put)
{ return c + '(' + e + ', function () { ' + s + ' });' }
bool_line = l:line_number { return '(N(' + l + ') > 0)'; }
primary =
paren
/ integer
/ call
paren = '(' space e:expression_integer space ')' { return '(' + e + ')'; }
expression_bool =
l:expression_bool_part space o:operator_bool space r:expression_bool { return l + ' ' + o + ' ' + r; }
/ o:operator_bool_unary e:expression_bool { return o + ' ' + e; }
/ expression_bool_part
bool_paren = '(' space e:expression_bool space ')' { return '(' + e + ')'; }
expression_bool_part =
bool_paren
/ bool_line
/ expression_cmp
expression_cmp =
l:expression_integer space o:operator_cmp space r:expression_integer { return l + ' ' + o + ' ' + r; }
expression_integer =
l:primary space o:operator_integer space r:expression_integer { return l + ' ' + o + ' ' + r; }
/ primary
call = N / U / put / print / read
N = n:('N' space '(' space expression_integer space ')') { return n.join(''); }
U = u:('U' space '(' space expression_integer space ')') { return u.join(''); }
print = 'print' space '(' space s:(string_expression) space ')' { return 'print(' + s + ');' }
put = 'put' space '(' space s:(string_expression) space ')' { return 'put(' + s + ');' }
read = 'read' space '(' space ')' { return 'read()' }
string_expression =
l:string_expression_1 space '+' space r:string_expression { return l + '+' + r; }
/ string_expression_1
string_expression_1 =
string
/ e:expression_integer { return '(' + e + ')' }
string = '"' s:[^"]* '"' { return '"' + s.join('') + '"'; }
integer = '-' i:positive_integer { return -i; }
/ positive_integer
positive_integer = i:([0-9]+) { return parseInt(i.join(''), 10); }
operator_bool = '&&' / '||'
operator_cmp = '!=' / '==' / '<=' / '>=' / '<' / '>'
operator_integer = '+' / '-' / '*' / '/' / '%'
operator_bool_unary = '!'
space = [ ]*