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