rkelly-turbo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.rdoc +38 -0
- data/Manifest.txt +203 -0
- data/README.rdoc +135 -0
- data/Rakefile +41 -0
- data/lib/parser.y +883 -0
- data/lib/rkelly.rb +14 -0
- data/lib/rkelly/char_pos.rb +39 -0
- data/lib/rkelly/char_range.rb +33 -0
- data/lib/rkelly/constants.rb +3 -0
- data/lib/rkelly/generated_parser.rb +3380 -0
- data/lib/rkelly/js.rb +14 -0
- data/lib/rkelly/js/array.rb +15 -0
- data/lib/rkelly/js/base.rb +91 -0
- data/lib/rkelly/js/boolean.rb +21 -0
- data/lib/rkelly/js/function.rb +39 -0
- data/lib/rkelly/js/function_prototype.rb +15 -0
- data/lib/rkelly/js/global_object.rb +52 -0
- data/lib/rkelly/js/math.rb +10 -0
- data/lib/rkelly/js/nan.rb +18 -0
- data/lib/rkelly/js/number.rb +22 -0
- data/lib/rkelly/js/object.rb +30 -0
- data/lib/rkelly/js/object_prototype.rb +14 -0
- data/lib/rkelly/js/property.rb +20 -0
- data/lib/rkelly/js/scope.rb +6 -0
- data/lib/rkelly/js/string.rb +21 -0
- data/lib/rkelly/lexeme.rb +18 -0
- data/lib/rkelly/nodes.rb +25 -0
- data/lib/rkelly/nodes/binary_node.rb +18 -0
- data/lib/rkelly/nodes/bracket_accessor_node.rb +11 -0
- data/lib/rkelly/nodes/case_clause_node.rb +11 -0
- data/lib/rkelly/nodes/comma_node.rb +11 -0
- data/lib/rkelly/nodes/conditional_node.rb +11 -0
- data/lib/rkelly/nodes/dot_accessor_node.rb +11 -0
- data/lib/rkelly/nodes/for_in_node.rb +12 -0
- data/lib/rkelly/nodes/for_node.rb +13 -0
- data/lib/rkelly/nodes/function_call_node.rb +16 -0
- data/lib/rkelly/nodes/function_decl_node.rb +6 -0
- data/lib/rkelly/nodes/function_expr_node.rb +12 -0
- data/lib/rkelly/nodes/if_node.rb +12 -0
- data/lib/rkelly/nodes/label_node.rb +11 -0
- data/lib/rkelly/nodes/new_expr_node.rb +11 -0
- data/lib/rkelly/nodes/node.rb +116 -0
- data/lib/rkelly/nodes/not_strict_equal_node.rb +6 -0
- data/lib/rkelly/nodes/op_equal_node.rb +16 -0
- data/lib/rkelly/nodes/postfix_node.rb +11 -0
- data/lib/rkelly/nodes/prefix_node.rb +6 -0
- data/lib/rkelly/nodes/property_node.rb +13 -0
- data/lib/rkelly/nodes/resolve_node.rb +19 -0
- data/lib/rkelly/nodes/strict_equal_node.rb +6 -0
- data/lib/rkelly/nodes/try_node.rb +13 -0
- data/lib/rkelly/nodes/var_decl_node.rb +15 -0
- data/lib/rkelly/parser.rb +106 -0
- data/lib/rkelly/runtime.rb +36 -0
- data/lib/rkelly/runtime/ruby_function.rb +13 -0
- data/lib/rkelly/runtime/scope_chain.rb +57 -0
- data/lib/rkelly/syntax_error.rb +4 -0
- data/lib/rkelly/token.rb +27 -0
- data/lib/rkelly/tokenizer.rb +255 -0
- data/lib/rkelly/visitable.rb +31 -0
- data/lib/rkelly/visitors.rb +4 -0
- data/lib/rkelly/visitors/dot_visitor.rb +228 -0
- data/lib/rkelly/visitors/ecma_visitor.rb +328 -0
- data/lib/rkelly/visitors/enumerable_visitor.rb +18 -0
- data/lib/rkelly/visitors/evaluation_visitor.rb +419 -0
- data/lib/rkelly/visitors/function_visitor.rb +46 -0
- data/lib/rkelly/visitors/pointcut_visitor.rb +31 -0
- data/lib/rkelly/visitors/real_sexp_visitor.rb +16 -0
- data/lib/rkelly/visitors/sexp_visitor.rb +373 -0
- data/lib/rkelly/visitors/visitor.rb +149 -0
- data/test/ecma_script_test_case.rb +21 -0
- data/test/execute_test_case.rb +16 -0
- data/test/execution_contexts/test_10_1_3-1.rb +32 -0
- data/test/expressions/test_11_3_1.rb +64 -0
- data/test/expressions/test_11_3_2.rb +64 -0
- data/test/expressions/test_11_4_2.rb +13 -0
- data/test/expressions/test_11_4_3.rb +52 -0
- data/test/expressions/test_11_4_4.rb +68 -0
- data/test/expressions/test_11_4_5.rb +69 -0
- data/test/expressions/test_11_4_6.rb +94 -0
- data/test/expressions/test_11_4_8.rb +28 -0
- data/test/expressions/test_11_4_9.rb +103 -0
- data/test/expressions/test_11_5_1.rb +51 -0
- data/test/expressions/test_11_5_2.rb +80 -0
- data/test/expressions/test_11_5_3.rb +88 -0
- data/test/expressions/test_11_6_1-1.rb +19 -0
- data/test/expressions/test_11_9_1.rb +19 -0
- data/test/function/test_15_3_1_1-1.rb +34 -0
- data/test/global_object/test_15_1_1_1.rb +29 -0
- data/test/global_object/test_15_1_1_2.rb +17 -0
- data/test/global_object/test_15_1_1_3.rb +9 -0
- data/test/helper.rb +5 -0
- data/test/node_test_case.rb +11 -0
- data/test/object/test_15_2_1_1.rb +257 -0
- data/test/object/test_15_2_1_2.rb +21 -0
- data/test/object/test_15_2_2_1.rb +52 -0
- data/test/statements/test_12_5-1.rb +27 -0
- data/test/test_add_node.rb +8 -0
- data/test/test_arguments_node.rb +8 -0
- data/test/test_array_node.rb +9 -0
- data/test/test_assign_expr_node.rb +8 -0
- data/test/test_automatic_semicolon_insertion.rb +137 -0
- data/test/test_bit_and_node.rb +8 -0
- data/test/test_bit_or_node.rb +8 -0
- data/test/test_bit_x_or_node.rb +8 -0
- data/test/test_bitwise_not_node.rb +8 -0
- data/test/test_block_node.rb +14 -0
- data/test/test_bracket_accessor_node.rb +16 -0
- data/test/test_break_node.rb +11 -0
- data/test/test_case_block_node.rb +11 -0
- data/test/test_case_clause_node.rb +15 -0
- data/test/test_char_pos.rb +39 -0
- data/test/test_char_range.rb +29 -0
- data/test/test_comma_node.rb +13 -0
- data/test/test_comments.rb +45 -0
- data/test/test_conditional_node.rb +17 -0
- data/test/test_const_statement_node.rb +14 -0
- data/test/test_continue_node.rb +11 -0
- data/test/test_delete_node.rb +8 -0
- data/test/test_divide_node.rb +8 -0
- data/test/test_do_while_node.rb +13 -0
- data/test/test_dot_accessor_node.rb +9 -0
- data/test/test_ecma_visitor.rb +213 -0
- data/test/test_element_node.rb +8 -0
- data/test/test_empty_statement_node.rb +8 -0
- data/test/test_equal_node.rb +8 -0
- data/test/test_evaluation_visitor.rb +66 -0
- data/test/test_expression_statement_node.rb +10 -0
- data/test/test_false_node.rb +8 -0
- data/test/test_for_in_node.rb +17 -0
- data/test/test_for_node.rb +24 -0
- data/test/test_function_body_node.rb +8 -0
- data/test/test_function_call_node.rb +10 -0
- data/test/test_function_decl_node.rb +16 -0
- data/test/test_function_expr_node.rb +16 -0
- data/test/test_function_visitor.rb +26 -0
- data/test/test_getter_property_node.rb +10 -0
- data/test/test_global_object.rb +49 -0
- data/test/test_greater_node.rb +8 -0
- data/test/test_greater_or_equal_node.rb +8 -0
- data/test/test_if_node.rb +17 -0
- data/test/test_in_node.rb +8 -0
- data/test/test_instance_of_node.rb +8 -0
- data/test/test_label_node.rb +13 -0
- data/test/test_left_shift_node.rb +8 -0
- data/test/test_less_node.rb +8 -0
- data/test/test_less_or_equal_node.rb +8 -0
- data/test/test_line_number.rb +81 -0
- data/test/test_logical_and_node.rb +8 -0
- data/test/test_logical_not_node.rb +8 -0
- data/test/test_logical_or_node.rb +8 -0
- data/test/test_modulus_node.rb +8 -0
- data/test/test_multiply_node.rb +8 -0
- data/test/test_new_expr_node.rb +9 -0
- data/test/test_not_equal_node.rb +8 -0
- data/test/test_not_strict_equal_node.rb +8 -0
- data/test/test_null_node.rb +8 -0
- data/test/test_number_node.rb +8 -0
- data/test/test_object_literal_node.rb +9 -0
- data/test/test_op_and_equal_node.rb +10 -0
- data/test/test_op_divide_equal_node.rb +10 -0
- data/test/test_op_equal_node.rb +10 -0
- data/test/test_op_l_shift_equal_node.rb +10 -0
- data/test/test_op_minus_equal_node.rb +10 -0
- data/test/test_op_mod_equal_node.rb +10 -0
- data/test/test_op_multiply_equal_node.rb +10 -0
- data/test/test_op_or_equal_node.rb +10 -0
- data/test/test_op_plus_equal_node.rb +10 -0
- data/test/test_op_r_shift_equal_node.rb +10 -0
- data/test/test_op_u_r_shift_equal_node.rb +10 -0
- data/test/test_op_x_or_equal_node.rb +10 -0
- data/test/test_parameter_node.rb +8 -0
- data/test/test_parser.rb +1434 -0
- data/test/test_pointcut_visitor.rb +34 -0
- data/test/test_postfix_node.rb +8 -0
- data/test/test_prefix_node.rb +8 -0
- data/test/test_property_node.rb +8 -0
- data/test/test_regexp_node.rb +8 -0
- data/test/test_resolve_node.rb +22 -0
- data/test/test_return_node.rb +11 -0
- data/test/test_right_shift_node.rb +8 -0
- data/test/test_rkelly.rb +19 -0
- data/test/test_runtime.rb +12 -0
- data/test/test_scope_chain.rb +50 -0
- data/test/test_setter_property_node.rb +10 -0
- data/test/test_source_elements.rb +9 -0
- data/test/test_strict_equal_node.rb +8 -0
- data/test/test_string_node.rb +8 -0
- data/test/test_subtract_node.rb +8 -0
- data/test/test_switch_node.rb +12 -0
- data/test/test_this_node.rb +8 -0
- data/test/test_throw_node.rb +7 -0
- data/test/test_tokenizer.rb +285 -0
- data/test/test_true_node.rb +8 -0
- data/test/test_try_node.rb +59 -0
- data/test/test_type_of_node.rb +8 -0
- data/test/test_unary_minus_node.rb +8 -0
- data/test/test_unary_plus_node.rb +8 -0
- data/test/test_unsigned_right_shift_node.rb +8 -0
- data/test/test_var_decl_node.rb +21 -0
- data/test/test_var_statement_node.rb +14 -0
- data/test/test_void_node.rb +8 -0
- data/test/test_while_node.rb +15 -0
- data/test/test_with_node.rb +8 -0
- metadata +293 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class BinaryNode < Node
|
4
|
+
attr_reader :left
|
5
|
+
def initialize(left, right)
|
6
|
+
super(right)
|
7
|
+
@left = left
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
%w[Subtract LessOrEqual GreaterOrEqual Add Multiply NotEqual
|
12
|
+
DoWhile Switch LogicalAnd UnsignedRightShift Modulus While
|
13
|
+
NotStrictEqual Less With In Greater BitOr StrictEqual LogicalOr
|
14
|
+
BitXOr LeftShift Equal BitAnd InstanceOf Divide RightShift].each do |node|
|
15
|
+
const_set "#{node}Node", Class.new(BinaryNode)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class FunctionCallNode < Node
|
4
|
+
attr_reader :arguments
|
5
|
+
def initialize(value, arguments)
|
6
|
+
super(value)
|
7
|
+
@arguments = arguments
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
super && @arguments == other.arguments
|
12
|
+
end
|
13
|
+
alias :=~ :==
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RKelly
|
4
|
+
module Nodes
|
5
|
+
class Node
|
6
|
+
include RKelly::Visitable
|
7
|
+
include RKelly::Visitors
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
attr_accessor :value, :comments, :range, :filename
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
@range = CharRange::EMPTY
|
14
|
+
end
|
15
|
+
|
16
|
+
def comments; @comments || []; end
|
17
|
+
|
18
|
+
# For backwards compatibility
|
19
|
+
def line
|
20
|
+
@range.from.line
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
other.is_a?(self.class) && @value == other.value
|
25
|
+
end
|
26
|
+
alias :=~ :==
|
27
|
+
|
28
|
+
def ===(other)
|
29
|
+
other.is_a?(self.class) && @value === other.value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Matches nodes with the given pattern (usually a class name of
|
33
|
+
# the node) and returns an instance of PointcutVisitor on which
|
34
|
+
# #matches can be invoked to get the list of AST nodes that
|
35
|
+
# matched.
|
36
|
+
#
|
37
|
+
# ast.pointcut(RKelly::Nodes::IfNode).matches --> array of nodes
|
38
|
+
#
|
39
|
+
def pointcut(pattern)
|
40
|
+
case pattern
|
41
|
+
when String
|
42
|
+
ast = RKelly::Parser.new.parse(pattern)
|
43
|
+
# Only take the first statement
|
44
|
+
finder = ast.value.first.class.name.end_with?("StatementNode") ?
|
45
|
+
ast.value.first.value : ast.value.first
|
46
|
+
visitor = PointcutVisitor.new(finder)
|
47
|
+
else
|
48
|
+
visitor = PointcutVisitor.new(pattern)
|
49
|
+
end
|
50
|
+
|
51
|
+
visitor.accept(self)
|
52
|
+
visitor
|
53
|
+
end
|
54
|
+
alias :/ :pointcut
|
55
|
+
|
56
|
+
# Generates an s-expression data structure like so:
|
57
|
+
#
|
58
|
+
# "var x = 10;" --> [:var, [[:var_decl, :x, [:assign, [:lit, 10]]]]]]
|
59
|
+
#
|
60
|
+
def to_sexp
|
61
|
+
SexpVisitor.new.accept(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Generates formatted and intented JavaScript source code.
|
65
|
+
def to_ecma
|
66
|
+
ECMAVisitor.new.accept(self)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Generates a graph description in DOT language. This can be
|
70
|
+
# fed into the dot program to generate a graph of the AST:
|
71
|
+
#
|
72
|
+
# $ dot -Tpng generated-graph.dot -o graph.png
|
73
|
+
#
|
74
|
+
def to_dots
|
75
|
+
visitor = DotVisitor.new
|
76
|
+
visitor.accept(self)
|
77
|
+
header = <<-END
|
78
|
+
digraph g {
|
79
|
+
graph [ rankdir = "TB" ];
|
80
|
+
node [
|
81
|
+
fontsize = "16"
|
82
|
+
shape = "ellipse"
|
83
|
+
];
|
84
|
+
edge [ ];
|
85
|
+
END
|
86
|
+
nodes = visitor.nodes.map { |x| x.to_s }.join("\n")
|
87
|
+
counter = 0
|
88
|
+
arrows = visitor.arrows.map { |x|
|
89
|
+
s = "#{x} [\nid = #{counter}\n];"
|
90
|
+
counter += 1
|
91
|
+
s
|
92
|
+
}.join("\n")
|
93
|
+
"#{header}\n#{nodes}\n#{arrows}\n}"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Loops through all the syntax nodes.
|
97
|
+
def each(&block)
|
98
|
+
EnumerableVisitor.new(block).accept(self)
|
99
|
+
end
|
100
|
+
|
101
|
+
# This CRASHES!
|
102
|
+
# It calls method #s which is nowhere to be found.
|
103
|
+
def to_real_sexp
|
104
|
+
RealSexpVisitor.new.accept(self)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
%w[EmptyStatement Parenthetical ExpressionStatement True Delete Return TypeOf
|
109
|
+
SourceElements Number LogicalNot AssignExpr FunctionBody
|
110
|
+
ObjectLiteral UnaryMinus Throw This BitwiseNot Element String
|
111
|
+
Array CaseBlock Null Break Parameter Block False Void Regexp
|
112
|
+
Arguments Attr Continue ConstStatement UnaryPlus VarStatement].each do |node|
|
113
|
+
eval "class #{node}Node < Node; end"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class OpEqualNode < Node
|
4
|
+
attr_reader :left
|
5
|
+
def initialize(left, right)
|
6
|
+
super(right)
|
7
|
+
@left = left
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
%w[Multiply Divide LShift Minus Plus Mod XOr RShift And URShift Or].each do |node|
|
12
|
+
eval "class Op#{node}EqualNode < OpEqualNode; end"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class ResolveNode < Node
|
4
|
+
def ==(other)
|
5
|
+
return true if super
|
6
|
+
if ('A'..'Z').include? @value[0]
|
7
|
+
place = [Object, Module, RKelly::Nodes].find { |x|
|
8
|
+
x.const_defined?(@value.to_sym)
|
9
|
+
}
|
10
|
+
return false unless place
|
11
|
+
klass = place.const_get(@value.to_sym)
|
12
|
+
return true if klass && other.is_a?(klass) || other.value.is_a?(klass)
|
13
|
+
end
|
14
|
+
false
|
15
|
+
end
|
16
|
+
alias :=~ :==
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class TryNode < Node
|
4
|
+
attr_reader :catch_var, :catch_block, :finally_block
|
5
|
+
def initialize(value, catch_var, catch_block, finally_block = nil)
|
6
|
+
super(value)
|
7
|
+
@catch_var = catch_var
|
8
|
+
@catch_block = catch_block
|
9
|
+
@finally_block = finally_block
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class VarDeclNode < Node
|
4
|
+
attr_accessor :name, :type
|
5
|
+
def initialize(name, value, constant = false)
|
6
|
+
super(value)
|
7
|
+
@name = name
|
8
|
+
@constant = constant
|
9
|
+
end
|
10
|
+
|
11
|
+
def constant?; @constant; end
|
12
|
+
def variable?; !@constant; end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rkelly/tokenizer'
|
4
|
+
require 'rkelly/generated_parser'
|
5
|
+
|
6
|
+
|
7
|
+
module RKelly
|
8
|
+
class Parser < RKelly::GeneratedParser
|
9
|
+
TOKENIZER = Tokenizer.new
|
10
|
+
|
11
|
+
RKelly::GeneratedParser.instance_methods.each do |im|
|
12
|
+
next unless im.to_s =~ /^_reduce_\d+$/
|
13
|
+
define_method im do |val, _values, result|
|
14
|
+
r = super(val.map { |v|
|
15
|
+
v.is_a?(Token) ? v.to_racc_token[1] : v
|
16
|
+
}, _values, result)
|
17
|
+
|
18
|
+
if r.respond_to? :range
|
19
|
+
suitable_values = val.flatten.find_all {|v| v.is_a? Token or v.is_a? Node }
|
20
|
+
first = suitable_values.first
|
21
|
+
if first
|
22
|
+
r.range = CharRange.new(first.range.from, suitable_values.last.range.to)
|
23
|
+
r.filename = @filename if @filename
|
24
|
+
end
|
25
|
+
end
|
26
|
+
r
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :logger
|
31
|
+
def initialize
|
32
|
+
@tokens = []
|
33
|
+
@logger = nil
|
34
|
+
@terminator = false
|
35
|
+
@prev_token = nil
|
36
|
+
@comments = []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Parse +javascript+ and return an AST
|
40
|
+
def parse(javascript, filename = nil)
|
41
|
+
@tokens = TOKENIZER.raw_tokens(javascript)
|
42
|
+
@position = 0
|
43
|
+
@filename = filename
|
44
|
+
ast = do_parse
|
45
|
+
ast.comments = @comments if ast
|
46
|
+
ast
|
47
|
+
end
|
48
|
+
|
49
|
+
def yyabort
|
50
|
+
raise "something bad happened, please report a bug with sample JavaScript"
|
51
|
+
end
|
52
|
+
|
53
|
+
# When parsing finishes without all tokens being parsed, returns
|
54
|
+
# the token at which the parsing stopped. Returns nil when parser
|
55
|
+
# reached to the very last token (but possibly still failed as it
|
56
|
+
# expeced more tokens).
|
57
|
+
#
|
58
|
+
# Useful for pin-pointing the position of a syntax error.
|
59
|
+
def stopped_at
|
60
|
+
if @position < @tokens.length
|
61
|
+
@tokens[@position-1]
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def on_error(error_token_id, error_value, value_stack)
|
69
|
+
if logger
|
70
|
+
logger.error(token_to_str(error_token_id))
|
71
|
+
logger.error("error value: #{error_value}")
|
72
|
+
logger.error("error stack: #{value_stack}")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
SEMICOLON_TOKEN = RKelly::Token.new(';', ';').freeze
|
77
|
+
|
78
|
+
def next_token
|
79
|
+
@terminator = false
|
80
|
+
begin
|
81
|
+
return [false, false] if @position >= @tokens.length
|
82
|
+
n_token = @tokens[@position]
|
83
|
+
@position += 1
|
84
|
+
case @tokens[@position - 1].name
|
85
|
+
when :COMMENT
|
86
|
+
@comments << n_token
|
87
|
+
@terminator = true if n_token.value.start_with? "//"
|
88
|
+
when :S
|
89
|
+
@terminator = true if n_token.value =~ /[\r\n]/
|
90
|
+
end
|
91
|
+
end while([:COMMENT, :S].include?(n_token.name))
|
92
|
+
|
93
|
+
if @terminator &&
|
94
|
+
((@prev_token && %w[continue break return throw].include?(@prev_token.value)) ||
|
95
|
+
(n_token && %w[++ --].include?(n_token.value)))
|
96
|
+
@position -= 1
|
97
|
+
return (@prev_token = SEMICOLON_TOKEN.dup).to_racc_token
|
98
|
+
end
|
99
|
+
|
100
|
+
@prev_token = n_token
|
101
|
+
v = n_token.to_racc_token
|
102
|
+
v[1] = n_token
|
103
|
+
v
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|