rkelly 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +7 -0
- data/Manifest.txt +199 -0
- data/README.txt +58 -0
- data/Rakefile +85 -0
- data/lib/parser.y +870 -0
- data/lib/rkelly.rb +13 -0
- data/lib/rkelly/constants.rb +3 -0
- data/lib/rkelly/generated_parser.rb +3237 -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 +5 -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 +88 -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 +100 -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/token.rb +15 -0
- data/lib/rkelly/tokenizer.rb +122 -0
- data/lib/rkelly/visitable.rb +16 -0
- data/lib/rkelly/visitors.rb +4 -0
- data/lib/rkelly/visitors/dot_visitor.rb +228 -0
- data/lib/rkelly/visitors/ecma_visitor.rb +314 -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 +136 -0
- data/rkelly.gemspec +33 -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 +88 -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_comma_node.rb +13 -0
- data/test/test_comments.rb +44 -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 +192 -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 +23 -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 +1355 -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 +143 -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 +390 -0
@@ -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,88 @@
|
|
1
|
+
module RKelly
|
2
|
+
module Nodes
|
3
|
+
class Node
|
4
|
+
include RKelly::Visitable
|
5
|
+
include RKelly::Visitors
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_accessor :value, :comments, :line, :filename
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
@comments = []
|
12
|
+
@filename = @line = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
other.is_a?(self.class) && @value == other.value
|
17
|
+
end
|
18
|
+
alias :=~ :==
|
19
|
+
|
20
|
+
def ===(other)
|
21
|
+
other.is_a?(self.class) && @value === other.value
|
22
|
+
end
|
23
|
+
|
24
|
+
def pointcut(pattern)
|
25
|
+
case pattern
|
26
|
+
when String
|
27
|
+
ast = RKelly::Parser.new.parse(pattern)
|
28
|
+
# Only take the first statement
|
29
|
+
finder = ast.value.first.class.to_s =~ /StatementNode$/ ?
|
30
|
+
ast.value.first.value : ast.value.first
|
31
|
+
visitor = PointcutVisitor.new(finder)
|
32
|
+
else
|
33
|
+
visitor = PointcutVisitor.new(pattern)
|
34
|
+
end
|
35
|
+
|
36
|
+
visitor.accept(self)
|
37
|
+
visitor
|
38
|
+
end
|
39
|
+
alias :/ :pointcut
|
40
|
+
|
41
|
+
def to_sexp
|
42
|
+
SexpVisitor.new.accept(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_ecma
|
46
|
+
ECMAVisitor.new.accept(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_dots
|
50
|
+
visitor = DotVisitor.new
|
51
|
+
visitor.accept(self)
|
52
|
+
header = <<-END
|
53
|
+
digraph g {
|
54
|
+
graph [ rankdir = "TB" ];
|
55
|
+
node [
|
56
|
+
fontsize = "16"
|
57
|
+
shape = "ellipse"
|
58
|
+
];
|
59
|
+
edge [ ];
|
60
|
+
END
|
61
|
+
nodes = visitor.nodes.map { |x| x.to_s }.join("\n")
|
62
|
+
counter = 0
|
63
|
+
arrows = visitor.arrows.map { |x|
|
64
|
+
s = "#{x} [\nid = #{counter}\n];"
|
65
|
+
counter += 1
|
66
|
+
s
|
67
|
+
}.join("\n")
|
68
|
+
"#{header}\n#{nodes}\n#{arrows}\n}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def each(&block)
|
72
|
+
EnumerableVisitor.new(block).accept(self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_real_sexp
|
76
|
+
RealSexpVisitor.new.accept(self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
%w[EmptyStatement ExpressionStatement True Delete Return TypeOf
|
81
|
+
SourceElements Number LogicalNot AssignExpr FunctionBody
|
82
|
+
ObjectLiteral UnaryMinus Throw This BitwiseNot Element String
|
83
|
+
Array CaseBlock Null Break Parameter Block False Void Regexp
|
84
|
+
Arguments Attr Continue ConstStatement UnaryPlus VarStatement].each do |node|
|
85
|
+
eval "class #{node}Node < Node; end"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
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 @value =~ /^[A-Z]/
|
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,100 @@
|
|
1
|
+
require 'rkelly/tokenizer'
|
2
|
+
require 'rkelly/generated_parser'
|
3
|
+
|
4
|
+
|
5
|
+
module RKelly
|
6
|
+
class Parser < RKelly::GeneratedParser
|
7
|
+
TOKENIZER = Tokenizer.new
|
8
|
+
|
9
|
+
RKelly::GeneratedParser.instance_methods.each do |im|
|
10
|
+
next unless im.to_s =~ /^_reduce_\d+$/
|
11
|
+
eval(<<-eoawesomehack)
|
12
|
+
def #{im}(val, _values, result)
|
13
|
+
r = super(val.map { |v|
|
14
|
+
v.is_a?(Token) ? v.to_racc_token[1] : v
|
15
|
+
}, _values, result)
|
16
|
+
if token = val.find { |v| v.is_a?(Token) }
|
17
|
+
r.line = token.line if r.respond_to?(:line)
|
18
|
+
r.filename = @filename if r.respond_to?(:filename)
|
19
|
+
end
|
20
|
+
r
|
21
|
+
end
|
22
|
+
eoawesomehack
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :logger
|
26
|
+
def initialize
|
27
|
+
@tokens = []
|
28
|
+
@logger = nil
|
29
|
+
@terminator = false
|
30
|
+
@prev_token = nil
|
31
|
+
@comments = []
|
32
|
+
end
|
33
|
+
|
34
|
+
# Parse +javascript+ and return an AST
|
35
|
+
def parse(javascript, filename = nil)
|
36
|
+
@tokens = TOKENIZER.raw_tokens(javascript)
|
37
|
+
@position = 0
|
38
|
+
@filename = filename
|
39
|
+
ast = do_parse
|
40
|
+
apply_comments(ast)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def apply_comments(ast)
|
45
|
+
ast_hash = Hash.new { |h,k| h[k] = [] }
|
46
|
+
(ast || []).each { |n|
|
47
|
+
next unless n.line
|
48
|
+
ast_hash[n.line] << n
|
49
|
+
}
|
50
|
+
max = ast_hash.keys.sort.last
|
51
|
+
@comments.each do |comment|
|
52
|
+
node = nil
|
53
|
+
comment.line.upto(max) do |line|
|
54
|
+
if ast_hash.key?(line)
|
55
|
+
node = ast_hash[line].first
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
node.comments << comment if node
|
60
|
+
end if max
|
61
|
+
ast
|
62
|
+
end
|
63
|
+
|
64
|
+
def on_error(error_token_id, error_value, value_stack)
|
65
|
+
if logger
|
66
|
+
logger.error(token_to_str(error_token_id))
|
67
|
+
logger.error("error value: #{error_value}")
|
68
|
+
logger.error("error stack: #{value_stack}")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def next_token
|
73
|
+
@terminator = false
|
74
|
+
begin
|
75
|
+
return [false, false] if @position >= @tokens.length
|
76
|
+
n_token = @tokens[@position]
|
77
|
+
@position += 1
|
78
|
+
case @tokens[@position - 1].name
|
79
|
+
when :COMMENT
|
80
|
+
@comments << n_token
|
81
|
+
@terminator = true if n_token.value =~ /^\/\//
|
82
|
+
when :S
|
83
|
+
@terminator = true if n_token.value =~ /[\r\n]/
|
84
|
+
end
|
85
|
+
end while([:COMMENT, :S].include?(n_token.name))
|
86
|
+
|
87
|
+
if @terminator &&
|
88
|
+
((@prev_token && %w[continue break return throw].include?(@prev_token.value)) ||
|
89
|
+
(n_token && %w[++ --].include?(n_token.value)))
|
90
|
+
@position -= 1
|
91
|
+
return (@prev_token = RKelly::Token.new(';', ';')).to_racc_token
|
92
|
+
end
|
93
|
+
|
94
|
+
@prev_token = n_token
|
95
|
+
v = n_token.to_racc_token
|
96
|
+
v[1] = n_token
|
97
|
+
v
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|