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.
Files changed (37) hide show
  1. data/lib/twostroke/ast/case.rb +1 -1
  2. data/lib/twostroke/ast/function.rb +2 -2
  3. data/lib/twostroke/ast/label.rb +20 -0
  4. data/lib/twostroke/ast/switch.rb +1 -0
  5. data/lib/twostroke/ast/try.rb +3 -3
  6. data/lib/twostroke/ast/unary_operators.rb +1 -1
  7. data/lib/twostroke/ast.rb +1 -0
  8. data/lib/twostroke/compiler/javascript.rb +20 -2
  9. data/lib/twostroke/compiler/tsasm.rb +89 -35
  10. data/lib/twostroke/compiler.rb +1 -1
  11. data/lib/twostroke/error.rb +3 -0
  12. data/lib/twostroke/lexer.rb +3 -2
  13. data/lib/twostroke/parser.rb +309 -227
  14. data/lib/twostroke/runtime/lib/array.js +9 -3
  15. data/lib/twostroke/runtime/lib/array.rb +15 -7
  16. data/lib/twostroke/runtime/lib/console.rb +3 -2
  17. data/lib/twostroke/runtime/lib/error.rb +1 -1
  18. data/lib/twostroke/runtime/lib/etc.js +38 -0
  19. data/lib/twostroke/runtime/lib/etc.rb +29 -0
  20. data/lib/twostroke/runtime/lib/math.rb +31 -0
  21. data/lib/twostroke/runtime/lib/number.rb +7 -1
  22. data/lib/twostroke/runtime/lib/object.rb +1 -1
  23. data/lib/twostroke/runtime/lib/regexp.rb +1 -0
  24. data/lib/twostroke/runtime/lib/string.rb +62 -22
  25. data/lib/twostroke/runtime/scope.rb +23 -2
  26. data/lib/twostroke/runtime/types/array.rb +5 -0
  27. data/lib/twostroke/runtime/types/function.rb +5 -2
  28. data/lib/twostroke/runtime/types/object.rb +3 -4
  29. data/lib/twostroke/runtime/types/regexp.rb +45 -2
  30. data/lib/twostroke/runtime/types.rb +1 -1
  31. data/lib/twostroke/runtime/vm.rb +2 -2
  32. data/lib/twostroke/runtime/vm_frame.rb +47 -8
  33. data/lib/twostroke/tokens.rb +32 -16
  34. metadata +5 -5
  35. data/lib/twostroke/ast/delete.rb +0 -15
  36. data/lib/twostroke/ast/unsorted_binop.rb +0 -97
  37. data/lib/twostroke/runtime/lib/function.js +0 -0
@@ -1,5 +1,5 @@
1
1
  module Twostroke
2
- class ParseError < Error
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 = true)
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 = true)
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 = true)
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
- next_token if try_peek_token && peek_token.type == :SEMICOLON
76
- #assert_type next_token, :SEMICOLON
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 expression(no_comma = false, no_in = false, no_ternary = false)
82
- expr = expression_after_unary no_comma
83
- expr = if [:PLUS, :MINUS, :ASTERISK, :SLASH, :MOD,
84
- :LEFT_SHIFT, :RIGHT_SHIFT, :RIGHT_TRIPLE_SHIFT,
85
- :AMPERSAND, :CARET, :PIPE ].include? peek_token(false).type
86
- state = save_state
87
- next_token
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
- expr
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 = if peek_token(false).type == :EQUALS
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::Assignment.new left: expr, right: expression(true)
117
- elsif !no_ternary && peek_token(false).type == :QUESTION
118
- ternary(expr)
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
- expr
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
- if !no_comma && peek_token(false).type == :COMMA
283
+ expr = call_expression
284
+
285
+ if peek_token.type == :INCREMENT
124
286
  next_token
125
- AST::MultiExpression.new left: expr, right: expression
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
- loop do
158
- if !no_call && peek_token(false).type == :OPEN_PAREN
159
- expr = call expr
160
- elsif peek_token(false).type == :OPEN_BRACKET
161
- expr = index expr
162
- elsif peek_token(false).type == :MEMBER_ACCESS
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 !no_comma && peek_token(false).type == :COMMA
165
- expr = comma(expr)
166
- elsif peek_token(false).type == :INCREMENT
167
- expr = post_increment 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 binop(left)
178
- op = next_token.type
179
- AST::UnsortedBinop.new left: left, op: op, right: expression(true, false, true)
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 = expression(false, true)
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(false)
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
- access = AST::MemberAccess.new object: obj, member: token.val
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 expression(true)
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(name: token.val)
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: expression(true)
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, expression(true)]
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 expression(true)
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