-
Notifications
You must be signed in to change notification settings - Fork 16
/
grammar.pegjs
100 lines (74 loc) · 1.64 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
// tinymath parsing grammar
start
= Expression
// characters
_ "whitespace"
= [ \t\n\r]*
Space
= [ ]
Quote
= [\"\']
StartChar
= [A-Za-z_@.\[\]-]
ValidChar
= [0-9A-Za-z._@\[\]-]
// literals and variables
Literal "literal"
= _ literal:(Number / VariableWithQuote / Variable) _ {
return literal;
}
Variable
= _ first:StartChar rest:ValidChar* _ { // We can open this up later. Strict for now.
return first + rest.join('');
}
VariableWithQuote
= _ Quote first:StartChar mid:(Space* ValidChar+)* Quote _ {
return first + mid.map(m => m[0].join('') + m[1].join('')).join('')
}
// expressions
Expression
= AddSubtract
AddSubtract
= _ left:MultiplyDivide rest:(('+' / '-') MultiplyDivide)* _ {
return rest.reduce((acc, curr) => ({
name: curr[0] === '+' ? 'add' : 'subtract',
args: [acc, curr[1]]
}), left)
}
MultiplyDivide
= _ left:Factor rest:(('*' / '/') Factor)* _ {
return rest.reduce((acc, curr) => ({
name: curr[0] === '*' ? 'multiply' : 'divide',
args: [acc, curr[1]]
}), left)
}
Factor
= Group
/ Function
/ Literal
Group
= _ '(' _ expr:Expression _ ')' _ {
return expr
}
Arguments "arguments"
= _ first:Expression rest:(_ ',' _ arg:Expression {return arg})* _ ','? _ {
return [first].concat(rest);
}
Function "function"
= _ name:[a-z]+ '(' _ args:Arguments? _ ')' _ {
return {name: name.join(''), args: args || []};
}
// Numbers. Lol.
Number "number"
= '-'? Integer Fraction? Exp? { return parseFloat(text()); }
E
= [eE]
Exp "exponent"
= E '-'? Digit+
Fraction
= '.' Digit+
Integer
= '0'
/ ([1-9] Digit*)
Digit
= [0-9]