/
Values.caf
206 lines (154 loc) · 5.68 KB
/
Values.caf
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import &StandardImport, &CaffeineEight
->
##
assignmentAccess cannot come directly after a functionAccessor
it must come after:
baseAccessor:
identifier
'@' identifier
propertyAccessor
bracketAccessor
2017-12-02
Thoughts on doing Existance-Checks without Transforms:
I'm thinking this is the right answer. Parse it into
the right structure to start with. Which is:
Function, property and bracket accessors are left-associative:
a.b.c becomes (((a).b).c)
The right-most accessor is the root.
Existance-checks have lower priority and are right-associative:
The left-most existance-check in an accessor chain
becomes the root.
a?.b.c becomes ((a)?((.b).c)
The second-left-most existance-check becomes the first-most's
direct right-child.
Etc.
Assignment:
Assignment throws a small wrench in the works.
If there is an existance-check in its left-children accessor
chain, that existance-check needs to be able to abort
the assignment.
Assignment is right-associative:
a=b=c becomes (a=(b=c))
Assuming we can get the parsing right, the magic happens at code-generation:
An existance-check Stn will perform value-capture with a temp variable.
Then it will pass the name of the temp-variable down to its right-child.
Accessors which get a value-capture-temp variable passed in for code-generation
pass it down to their left-child UNLESS they have no left-child. In that case,
the value-capture-temp becomes the left-child.
## @rule
valueWithoutExistanceCheck:
valueWithExistanceCheck:
"" valueWithoutExistanceCheck '?' accessorChain?
accessorChain:
:accessorChainWithExistanceCheck
:accessorChainWithoutExistanceCheck
accessorChainWithExistanceCheck:
"" accessorChainWithoutExistanceCheck '?' accessorChain?
accessorChainWithoutExistanceCheck:
"" accessor+
accessor:
:propertyAccessor
:bracketAccessor
:functionAccessor
:assignmentAccessor
value:
:valueWithExistanceCheck
:valueWithoutExistanceCheck
@rule
value:
"" valueBase blockValueExtension*"
"" newInstance valueExtension*
valueBase:
"" nonAssignableValue !accessorExtension
"" assignableValue assignmentExtension?
simpleAssignableValue:
:thisProperty
:identifierReference
assignableValue:
"" simpleAssignableValue accessorExtension* !functionInvocationExtension
"" '(' _? assignableValue _? ')' accessorExtension* !functionInvocationExtension
"" parentheticalExpression accessorExtension+
"" nonAssignableValue accessorExtension+
accessorExtension: :dotAccessor :bracketAccessor
nonAssignableValue:
:functionInvocation
:parentheticalExpression
:simpleNonAssignableValue
simpleValue:
:simpleNonAssignableValue
:simpleAssignableValue
simpleNonAssignableValue:
:require
:tagMacro
:globalIdentifier
:this
:literal
:super
functionInvocation:
"" simpleValue extendedFunctionInvocationExtension+
"" parentheticalExpression extendedFunctionInvocationExtension+
extendedFunctionInvocationExtension:
"" accessorExtension* functionInvocationExtension
@rule
simpleNewValue:
:this
:thisProperty
:globalIdentifier
:identifierReference
:require
newValue:
"" simpleNewValue accessorExtension*
"" parentheticalExpression accessorExtension*
explicitNewFunctionInvocation:
"newValue functionInvocationExtension"
# TODO: I think we need to convert this to a functionInvocation
# i.e. functionInvocation can take an optional 'new ' at the start
newInstance:
"new _ explicitNewFunctionInvocation"
"new _ newValue"
stnFactory: :NewInstanceStn
@rule
parentheticalExpression: "" '(' _? expression _? ')'
valueExtension: :dotAccessor :bracketAccessor :functionInvocationExtension :blockValueExtension
@rule
identifierReference:
pattern: "" !reservedWord identifier
stnFactory: :ReferenceStn
@rule
this: "/@/ !identifier"
thisProperty: "/@/ identifier assignmentExtension?"
{} stnFactory: :ThisStn
@rule
globalIdentifier:
pattern: /(global|require|module|eval|this)\b/
stnFactory: :GlobalIdentifierStn
stnProps: ~> identifier: @text
@rule
super:
pattern: "/super\\b/ superFunctionInvocation"
stnFactory: :SuperStn
@rule
super:
pattern: /super\b/
stnFactory: :SuperStn
stnProps: passArguments: true
@rule
blockValueExtension: "" _? blockValueExtensionBlock
blockValueExtensionBlock: Extensions.IndentBlocks.getPropsToSubparseBlock rule: :blockValueExtensionSubparse
blockValueExtensionSubparse:
"" lineStartComment* &dotOrQuestionDot valueExtension+ binaryOperatorSequenceExtension? newLineStatementExtension* end
"" lineStartComment* lineStartBinaryOperatorAndExpression newLineStatementExtension* end
dotOrQuestionDot: /\??\./
@rule
requiredValue:
"" _? _end? implicitArrayOrExpression
"" _? rValueBlock
rValueBlock: Extensions.IndentBlocks.getPropsToSubparseBlock rule: :rValueBlockSubParse
rValueBlockSubParse:
pattern: "root"
getStn: ~>
{statements} = @root
if statements.length == 1
statements[0].getStn()
else
&StnRegistry.ArrayStn @root.getMatchStns()