twostroke 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/twostroke/ast/case.rb +1 -1
- data/lib/twostroke/ast/function.rb +2 -2
- data/lib/twostroke/ast/label.rb +20 -0
- data/lib/twostroke/ast/switch.rb +1 -0
- data/lib/twostroke/ast/try.rb +3 -3
- data/lib/twostroke/ast/unary_operators.rb +1 -1
- data/lib/twostroke/ast.rb +1 -0
- data/lib/twostroke/compiler/javascript.rb +20 -2
- data/lib/twostroke/compiler/tsasm.rb +89 -35
- data/lib/twostroke/compiler.rb +1 -1
- data/lib/twostroke/error.rb +3 -0
- data/lib/twostroke/lexer.rb +3 -2
- data/lib/twostroke/parser.rb +309 -227
- data/lib/twostroke/runtime/lib/array.js +9 -3
- data/lib/twostroke/runtime/lib/array.rb +15 -7
- data/lib/twostroke/runtime/lib/console.rb +3 -2
- data/lib/twostroke/runtime/lib/error.rb +1 -1
- data/lib/twostroke/runtime/lib/etc.js +38 -0
- data/lib/twostroke/runtime/lib/etc.rb +29 -0
- data/lib/twostroke/runtime/lib/math.rb +31 -0
- data/lib/twostroke/runtime/lib/number.rb +7 -1
- data/lib/twostroke/runtime/lib/object.rb +1 -1
- data/lib/twostroke/runtime/lib/regexp.rb +1 -0
- data/lib/twostroke/runtime/lib/string.rb +62 -22
- data/lib/twostroke/runtime/scope.rb +23 -2
- data/lib/twostroke/runtime/types/array.rb +5 -0
- data/lib/twostroke/runtime/types/function.rb +5 -2
- data/lib/twostroke/runtime/types/object.rb +3 -4
- data/lib/twostroke/runtime/types/regexp.rb +45 -2
- data/lib/twostroke/runtime/types.rb +1 -1
- data/lib/twostroke/runtime/vm.rb +2 -2
- data/lib/twostroke/runtime/vm_frame.rb +47 -8
- data/lib/twostroke/tokens.rb +32 -16
- metadata +5 -5
- data/lib/twostroke/ast/delete.rb +0 -15
- data/lib/twostroke/ast/unsorted_binop.rb +0 -97
- data/lib/twostroke/runtime/lib/function.js +0 -0
data/lib/twostroke/parser.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Twostroke
|
2
|
-
class ParseError <
|
2
|
+
class ParseError < SyntaxError
|
3
3
|
end
|
4
4
|
|
5
5
|
class Parser
|
@@ -12,9 +12,9 @@ module Twostroke
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def parse
|
15
|
-
while try_peek_token
|
15
|
+
while try_peek_token(true)
|
16
16
|
st = statement
|
17
|
-
statements.push st.collapse if st
|
17
|
+
statements.push st.collapse if st # don't collapse
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -38,15 +38,15 @@ module Twostroke
|
|
38
38
|
def token
|
39
39
|
@cur_token or raise ParseError, "unexpected end of input"
|
40
40
|
end
|
41
|
-
def next_token(allow_regexp =
|
41
|
+
def next_token(allow_regexp = false)
|
42
42
|
@cur_token = @peek_token || @lexer.read_token(allow_regexp)
|
43
43
|
@peek_token = nil
|
44
44
|
token
|
45
45
|
end
|
46
|
-
def try_peek_token(allow_regexp =
|
46
|
+
def try_peek_token(allow_regexp = false)
|
47
47
|
@peek_token ||= @lexer.read_token(allow_regexp)
|
48
48
|
end
|
49
|
-
def peek_token(allow_regexp =
|
49
|
+
def peek_token(allow_regexp = false)
|
50
50
|
@peek_token ||= @lexer.read_token(allow_regexp) or raise ParseError, "unexpected end of input"
|
51
51
|
end
|
52
52
|
|
@@ -69,119 +69,290 @@ module Twostroke
|
|
69
69
|
when :OPEN_BRACE; consume_semicolon = false; body
|
70
70
|
when :FUNCTION; consume_semicolon = false; function
|
71
71
|
when :SEMICOLON; nil
|
72
|
+
when :LINE_TERMINATOR; nil
|
73
|
+
when :BAREWORD; label
|
72
74
|
else; expression
|
73
75
|
end
|
74
76
|
if consume_semicolon
|
75
|
-
|
76
|
-
|
77
|
+
if try_peek_token and peek_token.type == :SEMICOLON
|
78
|
+
next_token
|
79
|
+
end
|
77
80
|
end
|
78
81
|
st
|
79
82
|
end
|
80
|
-
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
combined = (peek_token(false).type == :EQUALS)
|
89
|
-
load_state state
|
90
|
-
if combined
|
91
|
-
# combination assignment
|
92
|
-
op = next_token(false).type
|
93
|
-
assert_type next_token(false), :EQUALS
|
94
|
-
AST::UnsortedBinop.operator_class[op].new left: expr, assign_result_left: true, right: expression(true, false, true)
|
95
|
-
else
|
96
|
-
binop expr
|
97
|
-
end
|
98
|
-
elsif [ :GT, :LT, :GTE, :LTE, :DOUBLE_EQUALS,
|
99
|
-
:TRIPLE_EQUALS, :NOT_EQUALS, :NOT_DOUBLE_EQUALS,
|
100
|
-
:AND, :OR, :LEFT_SHIFT, :RIGHT_SHIFT,
|
101
|
-
:RIGHT_TRIPLE_SHIFT, :INSTANCEOF,
|
102
|
-
*(no_in ? [] : [:IN]) ].include? peek_token(false).type
|
103
|
-
expr = binop expr
|
104
|
-
# this has a higher precedence than the ternary
|
105
|
-
# so we'll hackily check for a ternary after this
|
106
|
-
if !no_ternary && try_peek_token && peek_token(false).type == :QUESTION
|
107
|
-
ternary(expr)
|
108
|
-
else
|
109
|
-
expr
|
110
|
-
end
|
83
|
+
|
84
|
+
def label
|
85
|
+
state = save_state
|
86
|
+
assert_type next_token, :BAREWORD
|
87
|
+
name = token.val
|
88
|
+
if try_peek_token and peek_token.type == :COLON
|
89
|
+
next_token
|
90
|
+
return AST::Label.new name: name, line: token.line, statement: statement(false)
|
111
91
|
else
|
112
|
-
|
92
|
+
load_state state
|
93
|
+
expression
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def expression
|
98
|
+
multi_expression
|
99
|
+
end
|
100
|
+
|
101
|
+
def multi_expression
|
102
|
+
expr = assignment_expression
|
103
|
+
while try_peek_token and peek_token.type == :COMMA
|
104
|
+
next_token
|
105
|
+
expr = AST::MultiExpression.new left: expr, line: token.line, right: assignment_expression
|
106
|
+
end
|
107
|
+
expr
|
108
|
+
end
|
109
|
+
|
110
|
+
def assignment_expression
|
111
|
+
nodes = {
|
112
|
+
:ADD_EQUALS => AST::Addition,
|
113
|
+
:MINUS_EQUALS => AST::Subtraction,
|
114
|
+
:TIMES_EQUALS => AST::Multiplication,
|
115
|
+
:DIVIDE_EQUALS => AST::Division,
|
116
|
+
:MOD_EQUALS => AST::Modulus,
|
117
|
+
:LEFT_SHIFT => AST::LeftShift,
|
118
|
+
:RIGHT_SHIFT_EQUALS => AST::RightArithmeticShift,
|
119
|
+
:RIGHT_TRIPLE_SHIFT_EQUALS => AST::RightLogicalShift,
|
120
|
+
:BITWISE_AND_EQUALS => AST::BitwiseAnd,
|
121
|
+
:BITWISE_XOR_EQUALS => AST::BitwiseXor,
|
122
|
+
:BITWISE_OR_EQUALS => AST::BitwiseOr
|
123
|
+
}
|
124
|
+
expr = conditional_expression
|
125
|
+
if try_peek_token and peek_token.type == :EQUALS
|
126
|
+
next_token
|
127
|
+
expr = AST::Assignment.new left: expr, line: token.line, right: assignment_expression
|
128
|
+
elsif try_peek_token and nodes.keys.include? peek_token.type
|
129
|
+
expr = nodes[next_token.type].new left: expr, line: token.line, assign_result_left: true, right: assignment_expression
|
130
|
+
end
|
131
|
+
expr
|
132
|
+
end
|
133
|
+
|
134
|
+
def conditional_expression
|
135
|
+
cond = logical_or_expression
|
136
|
+
if try_peek_token and peek_token.type == :QUESTION
|
137
|
+
next_token
|
138
|
+
cond = AST::Ternary.new line: token.line, condition: cond
|
139
|
+
cond.if_true = assignment_expression
|
140
|
+
assert_type next_token, :COLON
|
141
|
+
cond.if_false = assignment_expression
|
142
|
+
end
|
143
|
+
cond
|
144
|
+
end
|
145
|
+
|
146
|
+
def logical_or_expression
|
147
|
+
expr = logical_and_expression
|
148
|
+
while try_peek_token and peek_token.type == :OR
|
149
|
+
next_token
|
150
|
+
expr = AST::Or.new left: expr, line: token.line, right: logical_and_expression
|
151
|
+
end
|
152
|
+
expr
|
153
|
+
end
|
154
|
+
|
155
|
+
def logical_and_expression
|
156
|
+
expr = bitwise_or_expression
|
157
|
+
while try_peek_token and peek_token.type == :AND
|
158
|
+
next_token
|
159
|
+
expr = AST::And.new left: expr, line: token.line, right: bitwise_or_expression
|
160
|
+
end
|
161
|
+
expr
|
162
|
+
end
|
163
|
+
|
164
|
+
def bitwise_or_expression
|
165
|
+
expr = bitwise_xor_expression
|
166
|
+
while try_peek_token and peek_token.type == :PIPE
|
167
|
+
next_token
|
168
|
+
expr = AST::BitwiseOr.new left: expr, line: token.line, right: bitwise_xor_expression
|
113
169
|
end
|
114
|
-
expr
|
170
|
+
expr
|
171
|
+
end
|
172
|
+
|
173
|
+
def bitwise_xor_expression
|
174
|
+
expr = bitwise_and_expression
|
175
|
+
while try_peek_token and peek_token.type == :CARET
|
176
|
+
next_token
|
177
|
+
expr = AST::BitwiseXor.new left: expr, line: token.line, right: bitwise_and_expression
|
178
|
+
end
|
179
|
+
expr
|
180
|
+
end
|
181
|
+
|
182
|
+
def bitwise_and_expression
|
183
|
+
expr = equality_expression
|
184
|
+
while try_peek_token and peek_token.type == :AMPERSAND
|
115
185
|
next_token
|
116
|
-
AST::
|
117
|
-
|
118
|
-
|
186
|
+
expr = AST::BitwiseAnd.new left: expr, line: token.line, right: equality_expression
|
187
|
+
end
|
188
|
+
expr
|
189
|
+
end
|
190
|
+
|
191
|
+
def equality_expression
|
192
|
+
nodes = {
|
193
|
+
:DOUBLE_EQUALS => AST::Equality,
|
194
|
+
:NOT_EQUALS => AST::Inequality,
|
195
|
+
:TRIPLE_EQUALS => AST::StrictEquality,
|
196
|
+
:NOT_DOUBLE_EQUALS => AST::StrictInequality
|
197
|
+
}
|
198
|
+
expr = relational_in_instanceof_expression
|
199
|
+
while try_peek_token and nodes.keys.include? peek_token.type
|
200
|
+
expr = nodes[next_token.type].new left: expr, line: token.line, right: relational_in_instanceof_expression
|
201
|
+
end
|
202
|
+
expr
|
203
|
+
end
|
204
|
+
|
205
|
+
def relational_in_instanceof_expression
|
206
|
+
nodes = {
|
207
|
+
:LT => AST::LessThan,
|
208
|
+
:LTE => AST::LessThanEqual,
|
209
|
+
:GT => AST::GreaterThan,
|
210
|
+
:GTE => AST::GreaterThanEqual,
|
211
|
+
:IN => AST::In,
|
212
|
+
:INSTANCEOF => AST::InstanceOf
|
213
|
+
}
|
214
|
+
expr = shift_expression
|
215
|
+
while try_peek_token(true) and nodes.keys.include? peek_token(true).type
|
216
|
+
expr = nodes[next_token(true).type].new left: expr, line: token.line, right: shift_expression
|
217
|
+
end
|
218
|
+
expr
|
219
|
+
end
|
220
|
+
|
221
|
+
def shift_expression
|
222
|
+
nodes = {
|
223
|
+
:LEFT_SHIFT => AST::LeftShift,
|
224
|
+
:RIGHT_TRIPLE_SHIFT => AST::RightArithmeticShift,
|
225
|
+
:RIGHT_SHIFT => AST::RightLogicalShift
|
226
|
+
}
|
227
|
+
expr = additive_expression
|
228
|
+
while try_peek_token and nodes.keys.include? peek_token.type
|
229
|
+
expr = nodes[next_token.type].new left: expr, line: token.line, right: additive_expression
|
230
|
+
end
|
231
|
+
expr
|
232
|
+
end
|
233
|
+
|
234
|
+
def additive_expression
|
235
|
+
nodes = {
|
236
|
+
:PLUS => AST::Addition,
|
237
|
+
:MINUS => AST::Subtraction
|
238
|
+
}
|
239
|
+
expr = multiplicative_expression
|
240
|
+
while try_peek_token and nodes.keys.include? peek_token.type
|
241
|
+
expr = nodes[next_token.type].new left: expr, line: token.line, right: multiplicative_expression
|
242
|
+
end
|
243
|
+
expr
|
244
|
+
end
|
245
|
+
|
246
|
+
def multiplicative_expression
|
247
|
+
nodes = {
|
248
|
+
:ASTERISK => AST::Multiplication,
|
249
|
+
:SLASH => AST::Division,
|
250
|
+
:MOD => AST::Modulus
|
251
|
+
}
|
252
|
+
expr = unary_expression
|
253
|
+
while try_peek_token and nodes.keys.include? peek_token.type
|
254
|
+
expr = nodes[next_token.type].new left: expr, line: token.line, right: unary_expression
|
255
|
+
end
|
256
|
+
expr
|
257
|
+
end
|
258
|
+
|
259
|
+
def unary_expression
|
260
|
+
case peek_token(true).type
|
261
|
+
when :NOT; next_token; AST::Not.new line: token.line, value: unary_expression
|
262
|
+
when :TILDE; next_token; AST::BinaryNot.new line: token.line, value: unary_expression
|
263
|
+
when :PLUS; next_token; AST::UnaryPlus.new line: token.line, value: unary_expression
|
264
|
+
when :MINUS; next_token; AST::Negation.new line: token.line, value: unary_expression
|
265
|
+
when :TYPEOF; next_token; AST::TypeOf.new line: token.line, value: unary_expression
|
266
|
+
when :VOID; next_token; AST::Void.new line: token.line, value: unary_expression
|
267
|
+
when :DELETE; next_token; AST::Delete.new line: token.line, value: unary_expression
|
119
268
|
else
|
120
|
-
|
269
|
+
increment_expression
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def increment_expression
|
274
|
+
if peek_token(true).type == :INCREMENT
|
275
|
+
next_token(true)
|
276
|
+
return AST::PreIncrement.new line: token.line, value: increment_expression
|
277
|
+
end
|
278
|
+
if peek_token(true).type == :DECREMENT
|
279
|
+
next_token(true)
|
280
|
+
return AST::PreDecrement.new line: token.line, value: increment_expression
|
121
281
|
end
|
122
282
|
|
123
|
-
|
283
|
+
expr = call_expression
|
284
|
+
|
285
|
+
if peek_token.type == :INCREMENT
|
124
286
|
next_token
|
125
|
-
AST::
|
126
|
-
else
|
127
|
-
expr
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def expression_after_unary(no_comma = true, no_call = false)
|
132
|
-
expr = case peek_token.type
|
133
|
-
when :FUNCTION; function
|
134
|
-
when :STRING; string
|
135
|
-
when :NUMBER; number
|
136
|
-
when :REGEXP; regexp
|
137
|
-
when :THIS; this
|
138
|
-
when :NULL; null
|
139
|
-
when :TRUE; send :true
|
140
|
-
when :FALSE; send :false
|
141
|
-
when :NEW; send :new
|
142
|
-
when :DELETE; delete
|
143
|
-
when :BAREWORD; bareword
|
144
|
-
when :OPEN_PAREN; parens
|
145
|
-
when :OPEN_BRACE; object_literal
|
146
|
-
when :OPEN_BRACKET; array
|
147
|
-
when :NOT; send :not
|
148
|
-
when :TILDE; tilde
|
149
|
-
when :INCREMENT; pre_increment
|
150
|
-
when :DECREMENT; pre_decrement
|
151
|
-
when :VOID; void
|
152
|
-
when :PLUS; unary_plus
|
153
|
-
when :MINUS; unary_minus
|
154
|
-
when :TYPEOF; typeof
|
155
|
-
else error! "Unexpected #{peek_token.type}"
|
287
|
+
return AST::PostIncrement.new line: token.line, value: expr
|
156
288
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
289
|
+
if peek_token.type == :DECREMENT
|
290
|
+
next_token
|
291
|
+
return AST::PostDecrement.new line: token.line, value: expr
|
292
|
+
end
|
293
|
+
|
294
|
+
expr
|
295
|
+
end
|
296
|
+
|
297
|
+
def call_expression
|
298
|
+
expr = value_expression
|
299
|
+
while try_peek_token and [:MEMBER_ACCESS, :OPEN_BRACKET, :OPEN_PAREN].include? peek_token.type
|
300
|
+
if peek_token.type == :MEMBER_ACCESS
|
163
301
|
expr = member_access expr
|
164
|
-
elsif
|
165
|
-
expr =
|
166
|
-
elsif peek_token
|
167
|
-
expr =
|
168
|
-
elsif peek_token(false).type == :DECREMENT
|
169
|
-
expr = post_decrement expr
|
170
|
-
else
|
171
|
-
return expr
|
302
|
+
elsif peek_token.type == :OPEN_BRACKET
|
303
|
+
expr = index expr
|
304
|
+
elsif peek_token.type == :OPEN_PAREN
|
305
|
+
expr = call expr
|
172
306
|
end
|
173
307
|
end
|
174
308
|
expr
|
175
309
|
end
|
176
310
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
311
|
+
def value_expression
|
312
|
+
case peek_token(true).type
|
313
|
+
when :FUNCTION; function
|
314
|
+
when :STRING; string
|
315
|
+
when :NUMBER; number
|
316
|
+
when :REGEXP; regexp
|
317
|
+
when :THIS; this
|
318
|
+
when :NULL; null
|
319
|
+
when :TRUE; send :true
|
320
|
+
when :FALSE; send :false
|
321
|
+
when :NEW; new
|
322
|
+
when :BAREWORD; bareword
|
323
|
+
when :OPEN_BRACKET; array
|
324
|
+
when :OPEN_BRACE; object_literal
|
325
|
+
when :OPEN_PAREN; parens
|
326
|
+
else error! "Unexpected #{peek_token.type}"
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def new
|
331
|
+
assert_type next_token, :NEW
|
332
|
+
node = AST::New.new line: token.line
|
333
|
+
node.callee = new_call_expression
|
334
|
+
if try_peek_token && peek_token.type == :OPEN_PAREN
|
335
|
+
call = call node.callee
|
336
|
+
node.arguments = call.arguments
|
337
|
+
end
|
338
|
+
node
|
339
|
+
end
|
340
|
+
|
341
|
+
def new_call_expression
|
342
|
+
expr = value_expression
|
343
|
+
while try_peek_token and [:MEMBER_ACCESS, :OPEN_BRACKET].include? peek_token.type
|
344
|
+
if peek_token.type == :MEMBER_ACCESS
|
345
|
+
expr = member_access expr
|
346
|
+
elsif peek_token.type == :OPEN_BRACKET
|
347
|
+
expr = index expr
|
348
|
+
end
|
349
|
+
end
|
350
|
+
expr
|
180
351
|
end
|
181
352
|
|
182
353
|
def body
|
183
354
|
assert_type next_token, :OPEN_BRACE
|
184
|
-
body = AST::Body.new
|
355
|
+
body = AST::Body.new line: token.line
|
185
356
|
while peek_token.type != :CLOSE_BRACE
|
186
357
|
body.statements.push statement
|
187
358
|
end
|
@@ -191,42 +362,33 @@ module Twostroke
|
|
191
362
|
|
192
363
|
def this
|
193
364
|
assert_type next_token, :THIS
|
194
|
-
AST::This.new
|
365
|
+
AST::This.new line: token.line
|
195
366
|
end
|
196
367
|
|
197
368
|
def null
|
198
369
|
assert_type next_token, :NULL
|
199
|
-
AST::Null.new
|
370
|
+
AST::Null.new line: token.line
|
200
371
|
end
|
201
372
|
|
202
373
|
def true
|
203
374
|
assert_type next_token, :TRUE
|
204
|
-
AST::True.new
|
375
|
+
AST::True.new line: token.line
|
205
376
|
end
|
206
377
|
|
207
378
|
def false
|
208
379
|
assert_type next_token, :FALSE
|
209
|
-
AST::False.new
|
380
|
+
AST::False.new line: token.line
|
210
381
|
end
|
211
382
|
|
212
383
|
def bareword
|
213
384
|
assert_type next_token, :BAREWORD
|
214
|
-
AST::Variable.new name: token.val
|
215
|
-
end
|
216
|
-
|
217
|
-
def ternary(cond)
|
218
|
-
assert_type next_token, :QUESTION
|
219
|
-
ternary = AST::Ternary.new condition: cond
|
220
|
-
ternary.if_true = expression(true)
|
221
|
-
assert_type next_token, :COLON
|
222
|
-
ternary.if_false = expression(true)
|
223
|
-
ternary
|
385
|
+
AST::Variable.new line: token.line, name: token.val
|
224
386
|
end
|
225
387
|
|
226
388
|
def with
|
227
389
|
assert_type next_token, :WITH
|
228
390
|
assert_type next_token, :OPEN_PAREN
|
229
|
-
with = AST::With.new object: expression
|
391
|
+
with = AST::With.new line: token.line, object: expression
|
230
392
|
assert_type next_token, :CLOSE_PAREN
|
231
393
|
with.statement = statement
|
232
394
|
with
|
@@ -235,7 +397,7 @@ module Twostroke
|
|
235
397
|
def if
|
236
398
|
assert_type next_token, :IF
|
237
399
|
assert_type next_token, :OPEN_PAREN
|
238
|
-
node = AST::If.new condition: expression
|
400
|
+
node = AST::If.new line: token.line, condition: expression
|
239
401
|
assert_type next_token, :CLOSE_PAREN
|
240
402
|
node.then = statement
|
241
403
|
if try_peek_token && peek_token.type == :ELSE
|
@@ -261,18 +423,18 @@ module Twostroke
|
|
261
423
|
end
|
262
424
|
load_state saved_state
|
263
425
|
if for_in
|
264
|
-
# no luck parsing for(;;), reparse as for(..in..)
|
426
|
+
# no luck parsing for(;;), reparse as for(..in..)
|
265
427
|
if peek_token.type == :VAR
|
266
428
|
next_token
|
267
429
|
assert_type next_token, :BAREWORD
|
268
|
-
lval = AST::Declaration.new name: token.val
|
430
|
+
lval = AST::Declaration.new line: token.line, name: token.val
|
269
431
|
else
|
270
|
-
lval =
|
432
|
+
lval = shift_expression # shift_expression is the precedence level right below in's
|
271
433
|
end
|
272
434
|
assert_type next_token, :IN
|
273
435
|
obj = expression
|
274
436
|
assert_type next_token, :CLOSE_PAREN
|
275
|
-
AST::ForIn.new lval: lval, object: obj, body: statement
|
437
|
+
AST::ForIn.new line: token.line, lval: lval, object: obj, body: statement
|
276
438
|
else
|
277
439
|
initializer = statement(false) unless peek_token.type == :SEMICOLON
|
278
440
|
assert_type next_token, :SEMICOLON
|
@@ -280,14 +442,14 @@ module Twostroke
|
|
280
442
|
assert_type next_token, :SEMICOLON
|
281
443
|
increment = statement(false) unless peek_token.type == :CLOSE_PAREN
|
282
444
|
assert_type next_token, :CLOSE_PAREN
|
283
|
-
AST::ForLoop.new initializer: initializer, condition: condition, increment: increment, body: statement
|
445
|
+
AST::ForLoop.new line: token.line, initializer: initializer, condition: condition, increment: increment, body: statement
|
284
446
|
end
|
285
447
|
end
|
286
448
|
|
287
449
|
def switch
|
288
450
|
assert_type next_token, :SWITCH
|
289
451
|
assert_type next_token, :OPEN_PAREN
|
290
|
-
sw = AST::Switch.new expression: expression
|
452
|
+
sw = AST::Switch.new line: token.line, expression: expression
|
291
453
|
assert_type next_token, :CLOSE_PAREN
|
292
454
|
assert_type next_token, :OPEN_BRACE
|
293
455
|
current_case = nil
|
@@ -296,7 +458,7 @@ module Twostroke
|
|
296
458
|
if peek_token.type == :CASE
|
297
459
|
assert_type next_token, :CASE
|
298
460
|
expr = expression
|
299
|
-
node = AST::Case.new expression: expr
|
461
|
+
node = AST::Case.new line: token.line, expression: expr
|
300
462
|
assert_type next_token, :COLON
|
301
463
|
sw.cases << node
|
302
464
|
current_case = node.statements
|
@@ -304,7 +466,7 @@ module Twostroke
|
|
304
466
|
assert_type next_token, :DEFAULT
|
305
467
|
error! "only one default case allowed" if default
|
306
468
|
default = true
|
307
|
-
node = AST::Case.new
|
469
|
+
node = AST::Case.new line: token.line
|
308
470
|
assert_type next_token, :COLON
|
309
471
|
sw.cases << node
|
310
472
|
current_case = node.statements
|
@@ -320,7 +482,7 @@ module Twostroke
|
|
320
482
|
def while
|
321
483
|
assert_type next_token, :WHILE
|
322
484
|
assert_type next_token, :OPEN_PAREN
|
323
|
-
node = AST::While.new condition: expression
|
485
|
+
node = AST::While.new line: token.line, condition: expression
|
324
486
|
assert_type next_token, :CLOSE_PAREN
|
325
487
|
node.body = statement
|
326
488
|
node
|
@@ -328,16 +490,16 @@ module Twostroke
|
|
328
490
|
|
329
491
|
def do
|
330
492
|
assert_type next_token, :DO
|
331
|
-
node = AST::DoWhile.new body: body
|
493
|
+
node = AST::DoWhile.new line: token.line, body: body
|
332
494
|
assert_type next_token, :WHILE
|
333
495
|
assert_type next_token, :OPEN_PAREN
|
334
|
-
node.condition = expression
|
496
|
+
node.condition = expression
|
335
497
|
assert_type next_token, :CLOSE_PAREN
|
336
498
|
node
|
337
499
|
end
|
338
500
|
|
339
501
|
def try
|
340
|
-
try = AST::Try.new try_statements: []
|
502
|
+
try = AST::Try.new line: token.line, try_statements: []
|
341
503
|
assert_type next_token, :TRY
|
342
504
|
assert_type next_token, :OPEN_BRACE
|
343
505
|
while peek_token.type != :CLOSE_BRACE
|
@@ -372,34 +534,14 @@ module Twostroke
|
|
372
534
|
def member_access(obj)
|
373
535
|
assert_type next_token, :MEMBER_ACCESS
|
374
536
|
assert_type next_token, :BAREWORD
|
375
|
-
|
376
|
-
if peek_token(false).type == :MEMBER_ACCESS
|
377
|
-
member_access access
|
378
|
-
elsif peek_token(false).type == :OPEN_PAREN
|
379
|
-
call access
|
380
|
-
elsif peek_token(false).type == :EQUALS
|
381
|
-
assignment access
|
382
|
-
else
|
383
|
-
access
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
def new
|
388
|
-
assert_type next_token, :NEW
|
389
|
-
node = AST::New.new
|
390
|
-
node.callee = expression_after_unary(true, true)
|
391
|
-
if try_peek_token && peek_token.type == :OPEN_PAREN
|
392
|
-
call = call(node.callee)
|
393
|
-
node.arguments = call.arguments
|
394
|
-
end
|
395
|
-
node
|
537
|
+
AST::MemberAccess.new line: token.line, object: obj, member: token.val
|
396
538
|
end
|
397
539
|
|
398
540
|
def call(callee)
|
399
541
|
assert_type next_token, :OPEN_PAREN
|
400
|
-
c = AST::Call.new callee: callee
|
401
|
-
while peek_token.type != :CLOSE_PAREN
|
402
|
-
c.arguments.push
|
542
|
+
c = AST::Call.new line: token.line, callee: callee
|
543
|
+
while peek_token(true).type != :CLOSE_PAREN
|
544
|
+
c.arguments.push assignment_expression # one level below multi_expression which can separate by comma
|
403
545
|
if peek_token.type == :COMMA
|
404
546
|
next_token
|
405
547
|
redo
|
@@ -413,33 +555,33 @@ module Twostroke
|
|
413
555
|
assert_type next_token, :OPEN_BRACKET
|
414
556
|
ind = expression
|
415
557
|
assert_type next_token, :CLOSE_BRACKET
|
416
|
-
AST::Index.new object: obj, index: ind
|
558
|
+
AST::Index.new line: token.line, object: obj, index: ind
|
417
559
|
end
|
418
560
|
|
419
561
|
def return
|
420
562
|
assert_type next_token, :RETURN
|
421
563
|
expr = expression unless peek_token.type == :SEMICOLON || peek_token.type == :CLOSE_BRACE
|
422
|
-
AST::Return.new expression: expr
|
564
|
+
AST::Return.new line: token.line, expression: expr
|
423
565
|
end
|
424
566
|
|
425
567
|
def break
|
426
568
|
assert_type next_token, :BREAK
|
427
|
-
AST::Break.new
|
569
|
+
AST::Break.new line: token.line
|
428
570
|
end
|
429
571
|
|
430
572
|
def continue
|
431
573
|
assert_type next_token, :CONTINUE
|
432
|
-
AST::Continue.new
|
574
|
+
AST::Continue.new line: token.line
|
433
575
|
end
|
434
576
|
|
435
577
|
def throw
|
436
578
|
assert_type next_token, :THROW
|
437
|
-
AST::Throw.new expression: expression
|
579
|
+
AST::Throw.new line: token.line, expression: expression
|
438
580
|
end
|
439
581
|
|
440
582
|
def delete
|
441
583
|
assert_type next_token, :DELETE
|
442
|
-
AST::Delete.new expression: expression
|
584
|
+
AST::Delete.new line: token.line, expression: expression
|
443
585
|
end
|
444
586
|
|
445
587
|
def var
|
@@ -449,59 +591,49 @@ module Twostroke
|
|
449
591
|
|
450
592
|
def var_rest
|
451
593
|
assert_type next_token, :BAREWORD
|
452
|
-
decl = AST::Declaration.new
|
594
|
+
decl = AST::Declaration.new line: token.line, name: token.val
|
453
595
|
return decl if peek_token.type == :SEMICOLON || peek_token.type == :CLOSE_BRACE
|
454
596
|
|
455
597
|
assert_type next_token, :COMMA, :EQUALS
|
456
598
|
|
457
599
|
if token.type == :COMMA
|
458
|
-
AST::MultiExpression.new left: decl, right: var_rest
|
600
|
+
AST::MultiExpression.new line: token.line, left: decl, right: var_rest
|
459
601
|
else
|
460
|
-
assignment = AST::Assignment.new left: decl, right:
|
602
|
+
assignment = AST::Assignment.new line: token.line, left: decl, right: assignment_expression
|
461
603
|
if peek_token.type == :SEMICOLON || peek_token.type == :CLOSE_BRACE
|
462
604
|
assignment
|
463
605
|
elsif peek_token.type == :COMMA
|
464
606
|
next_token
|
465
|
-
AST::MultiExpression.new left: assignment, right: var_rest
|
607
|
+
AST::MultiExpression.new line: token.line, left: assignment, right: var_rest
|
466
608
|
else
|
467
609
|
error! "Unexpected #{peek_token.type}"
|
468
610
|
end
|
469
611
|
end
|
470
612
|
end
|
471
613
|
|
472
|
-
def assignment(lval)
|
473
|
-
assert_type next_token, :EQUALS
|
474
|
-
AST::Assignment.new left: lval, right: expression
|
475
|
-
end
|
476
|
-
|
477
|
-
def comma(left)
|
478
|
-
assert_type next_token, :COMMA
|
479
|
-
AST::MultiExpression.new left: left, right: expression
|
480
|
-
end
|
481
|
-
|
482
614
|
def number
|
483
615
|
assert_type next_token, :NUMBER
|
484
|
-
AST::Number.new number: token.val
|
616
|
+
AST::Number.new line: token.line, number: token.val
|
485
617
|
end
|
486
618
|
|
487
619
|
def string
|
488
620
|
assert_type next_token, :STRING
|
489
|
-
AST::String.new string: token.val
|
621
|
+
AST::String.new line: token.line, string: token.val
|
490
622
|
end
|
491
623
|
|
492
624
|
def regexp
|
493
625
|
assert_type next_token, :REGEXP
|
494
|
-
AST::Regexp.new regexp: token.val
|
626
|
+
AST::Regexp.new line: token.line, regexp: token.val
|
495
627
|
end
|
496
628
|
|
497
629
|
def object_literal
|
498
630
|
assert_type next_token, :OPEN_BRACE
|
499
|
-
obj = AST::ObjectLiteral.new
|
631
|
+
obj = AST::ObjectLiteral.new line: token.line
|
500
632
|
while peek_token.type != :CLOSE_BRACE
|
501
633
|
assert_type next_token, :BAREWORD, :STRING, :NUMBER
|
502
634
|
key = token
|
503
635
|
assert_type next_token, :COLON
|
504
|
-
obj.items.push [key,
|
636
|
+
obj.items.push [key, assignment_expression]
|
505
637
|
if peek_token.type == :COMMA
|
506
638
|
next_token
|
507
639
|
redo
|
@@ -513,9 +645,9 @@ module Twostroke
|
|
513
645
|
|
514
646
|
def array
|
515
647
|
assert_type next_token, :OPEN_BRACKET
|
516
|
-
ary = AST::Array.new
|
517
|
-
while peek_token.type != :CLOSE_BRACKET
|
518
|
-
ary.items.push
|
648
|
+
ary = AST::Array.new line: token.line
|
649
|
+
while peek_token(true).type != :CLOSE_BRACKET
|
650
|
+
ary.items.push assignment_expression
|
519
651
|
if peek_token.type == :COMMA
|
520
652
|
next_token
|
521
653
|
redo
|
@@ -527,14 +659,14 @@ module Twostroke
|
|
527
659
|
|
528
660
|
def parens
|
529
661
|
assert_type next_token, :OPEN_PAREN
|
530
|
-
expr = AST::BracketedExpression.new value: expression
|
662
|
+
expr = AST::BracketedExpression.new line: token.line, value: expression
|
531
663
|
assert_type next_token, :CLOSE_PAREN
|
532
664
|
expr
|
533
665
|
end
|
534
666
|
|
535
667
|
def function
|
536
668
|
assert_type next_token, :FUNCTION
|
537
|
-
fn = AST::Function.new arguments: [], statements: []
|
669
|
+
fn = AST::Function.new line: token.line, arguments: [], statements: []
|
538
670
|
error! unless [:BAREWORD, :OPEN_PAREN].include? next_token.type
|
539
671
|
if token.type == :BAREWORD
|
540
672
|
fn.name = token.val
|
@@ -552,55 +684,5 @@ module Twostroke
|
|
552
684
|
assert_type next_token, :CLOSE_BRACE
|
553
685
|
fn
|
554
686
|
end
|
555
|
-
|
556
|
-
def not
|
557
|
-
assert_type next_token, :NOT
|
558
|
-
AST::Not.new value: expression_after_unary
|
559
|
-
end
|
560
|
-
|
561
|
-
def tilde
|
562
|
-
assert_type next_token, :TILDE
|
563
|
-
AST::BinaryNot.new value: expression_after_unary
|
564
|
-
end
|
565
|
-
|
566
|
-
def void
|
567
|
-
assert_type next_token, :VOID
|
568
|
-
AST::Void.new value: expression_after_unary
|
569
|
-
end
|
570
|
-
|
571
|
-
def unary_plus
|
572
|
-
assert_type next_token, :PLUS
|
573
|
-
AST::UnaryPlus.new value: expression_after_unary
|
574
|
-
end
|
575
|
-
|
576
|
-
def unary_minus
|
577
|
-
assert_type next_token, :MINUS
|
578
|
-
AST::Negation.new value: expression_after_unary
|
579
|
-
end
|
580
|
-
|
581
|
-
def post_increment(obj)
|
582
|
-
assert_type next_token, :INCREMENT
|
583
|
-
AST::PostIncrement.new value: obj
|
584
|
-
end
|
585
|
-
|
586
|
-
def post_decrement(obj)
|
587
|
-
assert_type next_token, :DECREMENT
|
588
|
-
AST::PostDecrement.new value: obj
|
589
|
-
end
|
590
|
-
|
591
|
-
def pre_increment
|
592
|
-
assert_type next_token, :INCREMENT
|
593
|
-
AST::PreIncrement.new value: expression_after_unary
|
594
|
-
end
|
595
|
-
|
596
|
-
def pre_decrement
|
597
|
-
assert_type next_token, :DECREMENT
|
598
|
-
AST::PreDecrement.new value: expression_after_unary
|
599
|
-
end
|
600
|
-
|
601
|
-
def typeof
|
602
|
-
assert_type next_token, :TYPEOF
|
603
|
-
AST::TypeOf.new value: expression_after_unary
|
604
|
-
end
|
605
687
|
end
|
606
688
|
end
|