twostroke 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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