-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrockstar-parser.peg
119 lines (101 loc) · 4.16 KB
/
rockstar-parser.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
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
Program = Statement *
Statement = _? s:(FunctionDeclaration/Operation/BlankLine) ','? _* '\n' {return s}
Operation = Loop / If / ArithmeticStatement / GiveBack / Set / Put / Listen / Say / Continue / Break / PoeticString
_ = ((' ' / '\t')+) / Comment
Comment = '(' [^)]* ')'
Variable =
(n:(CommonVariable / ProperVariable) {return {t: 'Variable', n}})
/ Pronoun {return {t: 'Pronoun'}}
CommonVariable = ('the'i/'my'i/'your'i) _ v:$([a-z]+) {return v}
ProperWord = $([A-Z][A-Za-z]+)
ProperVariable = $(ProperWord _ ProperVariable) / $ProperWord
Pronoun = (
'it'i
/'he'i/'she'i/'him'i/'her'i
/'them'i/'they'i
/'ze'i/'hir'i/'zie'i/'zir'i/'xe'i/'xem'i/'ve'i/'ver'i
)
TypeLiteral = v:TypeLiteralValue { return {t: 'Literal', v} }
TypeLiteralValue =
('nothing'/'nobody'/'nowhere'/'empty'/'gone') {return null}
/ ('true'/'right'/'yes'/'ok') {return true}
/ ('false'/'wrong'/'no'/'lies') {return false}
/ 'mysterious' { return undefined}
String = '"' v:$[^"]* '"'
{ return {t: 'Literal', v}}
Number = n:$('-'?[0-9]+('.'[0-9]+)?)
{ return {t: 'Literal', v: parseFloat(n)} }
ArithmeticStatement = BuildUp / KnockDown
BuildUp = 'Build' _ v:Variable _ 'up'
{ return {t: 'Rement', v: v, o: '++'} }
KnockDown = 'Knock' _ v:Variable _ 'down'
{ return {t: 'Rement', v: v, o: '--'} }
PoeticString = v:Variable _ 'says' ' ' t:$[^\n]*
{ return {t: 'Set', v: v, e: {t: 'Literal', v: t}} }
PoeticNumber = n:PoeticDigits d:PoeticDecimal? {return {t: 'Literal', v: parseFloat(d?n+'.'+d:n)}}
PoeticDecimal = '.' _ d:PoeticDigits {return d}
PoeticDigits =
l:PoeticDigit ( _ / [\',;:?!] )+ r:PoeticDigits { return l+r }
/ d: PoeticDigit { return d }
PoeticDigit = t:[A-Za-z]+ {return (t.length%10).toString()}
ArithmeticExpression =
l:SimpleExpression
_ o:ArithmeticOperator _
r:SimpleExpression
{ return {t: 'Arithmetic', l, o, r} }
ArithmeticOperator =
('minus'/'without') {return '-'}
/ ('plus'/'with') {return '+'}
/ ('times'/'of') {return '*'}
/ ('over') {return '/'}
Comparison = l:SimpleExpression _ b:BoolCheck c:Comparator? r:SimpleExpression
{ return {t: 'Comparison', l, r, b, c} }
BoolCheck =
(('is'_'not'_)/"ain't"_) { return false }
/ 'is'_ { return true }
Comparator =
('higher'/'greater'/'bigger'/'stronger')_'than'_ { return 'gt' }
/ ('lower'/'less'/'smaller'/'weaker')_'than'_ { return 'lt' }
/ 'as'_('high'/'great'/'big'/'strong')_'as'_ {return 'ge'}
/ 'as'_('low'/'little'/'small'/'weak')_'as'_ {return 'le'}
Listen = 'Listen' _ 'to' _ v:Variable
{return {t:'Listen', v}}
Say = ('Say'/'Shout'/'Whisper'/'Scream') _ e:Expression
{return {t:'Say', e}}
If = 'If' _ e:Expression
{ return {t: 'If', e} }
Else = 'Else' {return {t: 'Else'}}
Loop = c:('While'/'Until') _ e:Expression
{ return {t: 'Loop', c, e} }
Continue = ('Continue' / ('Take'_'it'_'to'_'the'_'top')) {return {t: 'Continue'}}
Break = ('Break' / ('Break'_'it'_'down')) {return {t: 'Break'}}
FunctionDeclaration = n:Variable _ 'takes' _ a:FunctionDeclarationArguments
{ return {t: 'FunctionDeclaration', n, a: a.map(a => a.n)} }
FunctionDeclarationArguments =
a:Variable (_'and'_ / _?','_?) b:FunctionDeclarationArguments { return [a].concat(b) }
/ a:Variable { return [a] }
GiveBack = 'Give back' _ e:Expression
{ return {t: 'GiveBack', e} }
BlankLine = '' {return {t: 'BlankLine'}}
FunctionCall = f:Variable _ 'taking' _ a:FunctionCallArguments
{ return {t: 'FunctionCall', f, a} }
// TODO 'and' is overloaded, so can't use full Expression syntax
FunctionCallArguments =
a:SimpleExpression (_'and'_ / _?','_?) b:FunctionCallArguments { return [a].concat(b) }
/ a:SimpleExpression { return [a] }
///////////////////////
// TODO Everything below here is never explicitly defined in the spec
Expression = ArithmeticExpression / BooleanOperation
SimpleExpression = FunctionCall / TypeLiteral / Variable / Number / String / PoeticNumber
BooleanOperation =
(
l:(Comparison / SimpleExpression)
_ b:('and'/'or') _
r:Expression
{ return {t: 'BooleanOperation', l, b, r} }
)
/ l: (Comparison / SimpleExpression) { return l }
Set = v:Variable _ ('is'/'was'/'were') _ e:Expression
{ return {t: 'Set', v: v, e} }
Put = 'Put' _ e:Expression _ 'into' _ v:Variable
{ return {t: 'Set', v: v, e} }