rkelly-turbo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +38 -0
  3. data/Manifest.txt +203 -0
  4. data/README.rdoc +135 -0
  5. data/Rakefile +41 -0
  6. data/lib/parser.y +883 -0
  7. data/lib/rkelly.rb +14 -0
  8. data/lib/rkelly/char_pos.rb +39 -0
  9. data/lib/rkelly/char_range.rb +33 -0
  10. data/lib/rkelly/constants.rb +3 -0
  11. data/lib/rkelly/generated_parser.rb +3380 -0
  12. data/lib/rkelly/js.rb +14 -0
  13. data/lib/rkelly/js/array.rb +15 -0
  14. data/lib/rkelly/js/base.rb +91 -0
  15. data/lib/rkelly/js/boolean.rb +21 -0
  16. data/lib/rkelly/js/function.rb +39 -0
  17. data/lib/rkelly/js/function_prototype.rb +15 -0
  18. data/lib/rkelly/js/global_object.rb +52 -0
  19. data/lib/rkelly/js/math.rb +10 -0
  20. data/lib/rkelly/js/nan.rb +18 -0
  21. data/lib/rkelly/js/number.rb +22 -0
  22. data/lib/rkelly/js/object.rb +30 -0
  23. data/lib/rkelly/js/object_prototype.rb +14 -0
  24. data/lib/rkelly/js/property.rb +20 -0
  25. data/lib/rkelly/js/scope.rb +6 -0
  26. data/lib/rkelly/js/string.rb +21 -0
  27. data/lib/rkelly/lexeme.rb +18 -0
  28. data/lib/rkelly/nodes.rb +25 -0
  29. data/lib/rkelly/nodes/binary_node.rb +18 -0
  30. data/lib/rkelly/nodes/bracket_accessor_node.rb +11 -0
  31. data/lib/rkelly/nodes/case_clause_node.rb +11 -0
  32. data/lib/rkelly/nodes/comma_node.rb +11 -0
  33. data/lib/rkelly/nodes/conditional_node.rb +11 -0
  34. data/lib/rkelly/nodes/dot_accessor_node.rb +11 -0
  35. data/lib/rkelly/nodes/for_in_node.rb +12 -0
  36. data/lib/rkelly/nodes/for_node.rb +13 -0
  37. data/lib/rkelly/nodes/function_call_node.rb +16 -0
  38. data/lib/rkelly/nodes/function_decl_node.rb +6 -0
  39. data/lib/rkelly/nodes/function_expr_node.rb +12 -0
  40. data/lib/rkelly/nodes/if_node.rb +12 -0
  41. data/lib/rkelly/nodes/label_node.rb +11 -0
  42. data/lib/rkelly/nodes/new_expr_node.rb +11 -0
  43. data/lib/rkelly/nodes/node.rb +116 -0
  44. data/lib/rkelly/nodes/not_strict_equal_node.rb +6 -0
  45. data/lib/rkelly/nodes/op_equal_node.rb +16 -0
  46. data/lib/rkelly/nodes/postfix_node.rb +11 -0
  47. data/lib/rkelly/nodes/prefix_node.rb +6 -0
  48. data/lib/rkelly/nodes/property_node.rb +13 -0
  49. data/lib/rkelly/nodes/resolve_node.rb +19 -0
  50. data/lib/rkelly/nodes/strict_equal_node.rb +6 -0
  51. data/lib/rkelly/nodes/try_node.rb +13 -0
  52. data/lib/rkelly/nodes/var_decl_node.rb +15 -0
  53. data/lib/rkelly/parser.rb +106 -0
  54. data/lib/rkelly/runtime.rb +36 -0
  55. data/lib/rkelly/runtime/ruby_function.rb +13 -0
  56. data/lib/rkelly/runtime/scope_chain.rb +57 -0
  57. data/lib/rkelly/syntax_error.rb +4 -0
  58. data/lib/rkelly/token.rb +27 -0
  59. data/lib/rkelly/tokenizer.rb +255 -0
  60. data/lib/rkelly/visitable.rb +31 -0
  61. data/lib/rkelly/visitors.rb +4 -0
  62. data/lib/rkelly/visitors/dot_visitor.rb +228 -0
  63. data/lib/rkelly/visitors/ecma_visitor.rb +328 -0
  64. data/lib/rkelly/visitors/enumerable_visitor.rb +18 -0
  65. data/lib/rkelly/visitors/evaluation_visitor.rb +419 -0
  66. data/lib/rkelly/visitors/function_visitor.rb +46 -0
  67. data/lib/rkelly/visitors/pointcut_visitor.rb +31 -0
  68. data/lib/rkelly/visitors/real_sexp_visitor.rb +16 -0
  69. data/lib/rkelly/visitors/sexp_visitor.rb +373 -0
  70. data/lib/rkelly/visitors/visitor.rb +149 -0
  71. data/test/ecma_script_test_case.rb +21 -0
  72. data/test/execute_test_case.rb +16 -0
  73. data/test/execution_contexts/test_10_1_3-1.rb +32 -0
  74. data/test/expressions/test_11_3_1.rb +64 -0
  75. data/test/expressions/test_11_3_2.rb +64 -0
  76. data/test/expressions/test_11_4_2.rb +13 -0
  77. data/test/expressions/test_11_4_3.rb +52 -0
  78. data/test/expressions/test_11_4_4.rb +68 -0
  79. data/test/expressions/test_11_4_5.rb +69 -0
  80. data/test/expressions/test_11_4_6.rb +94 -0
  81. data/test/expressions/test_11_4_8.rb +28 -0
  82. data/test/expressions/test_11_4_9.rb +103 -0
  83. data/test/expressions/test_11_5_1.rb +51 -0
  84. data/test/expressions/test_11_5_2.rb +80 -0
  85. data/test/expressions/test_11_5_3.rb +88 -0
  86. data/test/expressions/test_11_6_1-1.rb +19 -0
  87. data/test/expressions/test_11_9_1.rb +19 -0
  88. data/test/function/test_15_3_1_1-1.rb +34 -0
  89. data/test/global_object/test_15_1_1_1.rb +29 -0
  90. data/test/global_object/test_15_1_1_2.rb +17 -0
  91. data/test/global_object/test_15_1_1_3.rb +9 -0
  92. data/test/helper.rb +5 -0
  93. data/test/node_test_case.rb +11 -0
  94. data/test/object/test_15_2_1_1.rb +257 -0
  95. data/test/object/test_15_2_1_2.rb +21 -0
  96. data/test/object/test_15_2_2_1.rb +52 -0
  97. data/test/statements/test_12_5-1.rb +27 -0
  98. data/test/test_add_node.rb +8 -0
  99. data/test/test_arguments_node.rb +8 -0
  100. data/test/test_array_node.rb +9 -0
  101. data/test/test_assign_expr_node.rb +8 -0
  102. data/test/test_automatic_semicolon_insertion.rb +137 -0
  103. data/test/test_bit_and_node.rb +8 -0
  104. data/test/test_bit_or_node.rb +8 -0
  105. data/test/test_bit_x_or_node.rb +8 -0
  106. data/test/test_bitwise_not_node.rb +8 -0
  107. data/test/test_block_node.rb +14 -0
  108. data/test/test_bracket_accessor_node.rb +16 -0
  109. data/test/test_break_node.rb +11 -0
  110. data/test/test_case_block_node.rb +11 -0
  111. data/test/test_case_clause_node.rb +15 -0
  112. data/test/test_char_pos.rb +39 -0
  113. data/test/test_char_range.rb +29 -0
  114. data/test/test_comma_node.rb +13 -0
  115. data/test/test_comments.rb +45 -0
  116. data/test/test_conditional_node.rb +17 -0
  117. data/test/test_const_statement_node.rb +14 -0
  118. data/test/test_continue_node.rb +11 -0
  119. data/test/test_delete_node.rb +8 -0
  120. data/test/test_divide_node.rb +8 -0
  121. data/test/test_do_while_node.rb +13 -0
  122. data/test/test_dot_accessor_node.rb +9 -0
  123. data/test/test_ecma_visitor.rb +213 -0
  124. data/test/test_element_node.rb +8 -0
  125. data/test/test_empty_statement_node.rb +8 -0
  126. data/test/test_equal_node.rb +8 -0
  127. data/test/test_evaluation_visitor.rb +66 -0
  128. data/test/test_expression_statement_node.rb +10 -0
  129. data/test/test_false_node.rb +8 -0
  130. data/test/test_for_in_node.rb +17 -0
  131. data/test/test_for_node.rb +24 -0
  132. data/test/test_function_body_node.rb +8 -0
  133. data/test/test_function_call_node.rb +10 -0
  134. data/test/test_function_decl_node.rb +16 -0
  135. data/test/test_function_expr_node.rb +16 -0
  136. data/test/test_function_visitor.rb +26 -0
  137. data/test/test_getter_property_node.rb +10 -0
  138. data/test/test_global_object.rb +49 -0
  139. data/test/test_greater_node.rb +8 -0
  140. data/test/test_greater_or_equal_node.rb +8 -0
  141. data/test/test_if_node.rb +17 -0
  142. data/test/test_in_node.rb +8 -0
  143. data/test/test_instance_of_node.rb +8 -0
  144. data/test/test_label_node.rb +13 -0
  145. data/test/test_left_shift_node.rb +8 -0
  146. data/test/test_less_node.rb +8 -0
  147. data/test/test_less_or_equal_node.rb +8 -0
  148. data/test/test_line_number.rb +81 -0
  149. data/test/test_logical_and_node.rb +8 -0
  150. data/test/test_logical_not_node.rb +8 -0
  151. data/test/test_logical_or_node.rb +8 -0
  152. data/test/test_modulus_node.rb +8 -0
  153. data/test/test_multiply_node.rb +8 -0
  154. data/test/test_new_expr_node.rb +9 -0
  155. data/test/test_not_equal_node.rb +8 -0
  156. data/test/test_not_strict_equal_node.rb +8 -0
  157. data/test/test_null_node.rb +8 -0
  158. data/test/test_number_node.rb +8 -0
  159. data/test/test_object_literal_node.rb +9 -0
  160. data/test/test_op_and_equal_node.rb +10 -0
  161. data/test/test_op_divide_equal_node.rb +10 -0
  162. data/test/test_op_equal_node.rb +10 -0
  163. data/test/test_op_l_shift_equal_node.rb +10 -0
  164. data/test/test_op_minus_equal_node.rb +10 -0
  165. data/test/test_op_mod_equal_node.rb +10 -0
  166. data/test/test_op_multiply_equal_node.rb +10 -0
  167. data/test/test_op_or_equal_node.rb +10 -0
  168. data/test/test_op_plus_equal_node.rb +10 -0
  169. data/test/test_op_r_shift_equal_node.rb +10 -0
  170. data/test/test_op_u_r_shift_equal_node.rb +10 -0
  171. data/test/test_op_x_or_equal_node.rb +10 -0
  172. data/test/test_parameter_node.rb +8 -0
  173. data/test/test_parser.rb +1434 -0
  174. data/test/test_pointcut_visitor.rb +34 -0
  175. data/test/test_postfix_node.rb +8 -0
  176. data/test/test_prefix_node.rb +8 -0
  177. data/test/test_property_node.rb +8 -0
  178. data/test/test_regexp_node.rb +8 -0
  179. data/test/test_resolve_node.rb +22 -0
  180. data/test/test_return_node.rb +11 -0
  181. data/test/test_right_shift_node.rb +8 -0
  182. data/test/test_rkelly.rb +19 -0
  183. data/test/test_runtime.rb +12 -0
  184. data/test/test_scope_chain.rb +50 -0
  185. data/test/test_setter_property_node.rb +10 -0
  186. data/test/test_source_elements.rb +9 -0
  187. data/test/test_strict_equal_node.rb +8 -0
  188. data/test/test_string_node.rb +8 -0
  189. data/test/test_subtract_node.rb +8 -0
  190. data/test/test_switch_node.rb +12 -0
  191. data/test/test_this_node.rb +8 -0
  192. data/test/test_throw_node.rb +7 -0
  193. data/test/test_tokenizer.rb +285 -0
  194. data/test/test_true_node.rb +8 -0
  195. data/test/test_try_node.rb +59 -0
  196. data/test/test_type_of_node.rb +8 -0
  197. data/test/test_unary_minus_node.rb +8 -0
  198. data/test/test_unary_plus_node.rb +8 -0
  199. data/test/test_unsigned_right_shift_node.rb +8 -0
  200. data/test/test_var_decl_node.rb +21 -0
  201. data/test/test_var_statement_node.rb +14 -0
  202. data/test/test_void_node.rb +8 -0
  203. data/test/test_while_node.rb +15 -0
  204. data/test/test_with_node.rb +8 -0
  205. metadata +293 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: aef98d0989a1aa032fe7e0231129fb518d13c45ff7b359ce4f805fb40a23116e
4
+ data.tar.gz: 2aef9b143d414fb8c9dc3ddcc67d51e674375d7889ccdc738fe6f909bbeaf239
5
+ SHA512:
6
+ metadata.gz: 95c57e77d03ed1bc68daabb5cc8450b2fba7cad9bc98dcbea9c2cc7443386f87b90b9369f553dd0c29ce4154701763783385deb9d3f1f1a30f9232cbd110c3d9
7
+ data.tar.gz: a562b85535364137bd5675506e9c56054be829dbac4d4e347da000bc548a5d33e71adc20baa316c179027a66e10385a6ce7ed410a0248a661d8c05011f5e3c2e
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,38 @@
1
+ = RKelly-Turbo CHANGELOG
2
+
3
+ === 0.1.0
4
+
5
+ * Gain about 2x speedup by enacting some optimizations.
6
+
7
+ === 0.0.7
8
+
9
+ * Allow reserved words reserved only in strict mode.
10
+
11
+ === 0.0.6
12
+
13
+ * Properly treat all unicode whitespace characters as whitespace.
14
+
15
+ === 0.0.5
16
+
17
+ * Update list of reserved words to match ECMAScript 5
18
+ * Fix ecma visitor for function expressions with name
19
+
20
+ === 0.0.4
21
+
22
+ * Allow use of keywords in property names.
23
+
24
+ === 0.0.3
25
+
26
+ * Add RKelly::Parser#stopped_at method for error reporting.
27
+
28
+ === 0.0.2
29
+
30
+ * Handle multibyte characters without crashing.
31
+
32
+ === 0.0.1
33
+
34
+ * A fork of RKelly
35
+ * 10x speedup of Tokenizer.
36
+ * Full begin/end line/char info on each node.
37
+ * List all comment nodes in root node instead of attempting to associate them with syntax nodes and failing at it.
38
+ * Recognize /[/]/ as valid JS regex.
data/Manifest.txt ADDED
@@ -0,0 +1,203 @@
1
+ CHANGELOG.rdoc
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/parser.y
6
+ lib/rkelly.rb
7
+ lib/rkelly/char_pos.rb
8
+ lib/rkelly/char_range.rb
9
+ lib/rkelly/constants.rb
10
+ lib/rkelly/generated_parser.rb
11
+ lib/rkelly/js.rb
12
+ lib/rkelly/js/array.rb
13
+ lib/rkelly/js/base.rb
14
+ lib/rkelly/js/boolean.rb
15
+ lib/rkelly/js/function.rb
16
+ lib/rkelly/js/function_prototype.rb
17
+ lib/rkelly/js/global_object.rb
18
+ lib/rkelly/js/math.rb
19
+ lib/rkelly/js/nan.rb
20
+ lib/rkelly/js/number.rb
21
+ lib/rkelly/js/object.rb
22
+ lib/rkelly/js/object_prototype.rb
23
+ lib/rkelly/js/property.rb
24
+ lib/rkelly/js/scope.rb
25
+ lib/rkelly/js/string.rb
26
+ lib/rkelly/lexeme.rb
27
+ lib/rkelly/nodes.rb
28
+ lib/rkelly/nodes/binary_node.rb
29
+ lib/rkelly/nodes/bracket_accessor_node.rb
30
+ lib/rkelly/nodes/case_clause_node.rb
31
+ lib/rkelly/nodes/comma_node.rb
32
+ lib/rkelly/nodes/conditional_node.rb
33
+ lib/rkelly/nodes/dot_accessor_node.rb
34
+ lib/rkelly/nodes/for_in_node.rb
35
+ lib/rkelly/nodes/for_node.rb
36
+ lib/rkelly/nodes/function_call_node.rb
37
+ lib/rkelly/nodes/function_decl_node.rb
38
+ lib/rkelly/nodes/function_expr_node.rb
39
+ lib/rkelly/nodes/if_node.rb
40
+ lib/rkelly/nodes/label_node.rb
41
+ lib/rkelly/nodes/new_expr_node.rb
42
+ lib/rkelly/nodes/node.rb
43
+ lib/rkelly/nodes/not_strict_equal_node.rb
44
+ lib/rkelly/nodes/op_equal_node.rb
45
+ lib/rkelly/nodes/postfix_node.rb
46
+ lib/rkelly/nodes/prefix_node.rb
47
+ lib/rkelly/nodes/property_node.rb
48
+ lib/rkelly/nodes/resolve_node.rb
49
+ lib/rkelly/nodes/strict_equal_node.rb
50
+ lib/rkelly/nodes/try_node.rb
51
+ lib/rkelly/nodes/var_decl_node.rb
52
+ lib/rkelly/parser.rb
53
+ lib/rkelly/runtime.rb
54
+ lib/rkelly/runtime/ruby_function.rb
55
+ lib/rkelly/runtime/scope_chain.rb
56
+ lib/rkelly/syntax_error.rb
57
+ lib/rkelly/token.rb
58
+ lib/rkelly/tokenizer.rb
59
+ lib/rkelly/visitable.rb
60
+ lib/rkelly/visitors.rb
61
+ lib/rkelly/visitors/dot_visitor.rb
62
+ lib/rkelly/visitors/ecma_visitor.rb
63
+ lib/rkelly/visitors/enumerable_visitor.rb
64
+ lib/rkelly/visitors/evaluation_visitor.rb
65
+ lib/rkelly/visitors/function_visitor.rb
66
+ lib/rkelly/visitors/pointcut_visitor.rb
67
+ lib/rkelly/visitors/real_sexp_visitor.rb
68
+ lib/rkelly/visitors/sexp_visitor.rb
69
+ lib/rkelly/visitors/visitor.rb
70
+ test/ecma_script_test_case.rb
71
+ test/execute_test_case.rb
72
+ test/execution_contexts/test_10_1_3-1.rb
73
+ test/expressions/test_11_3_1.rb
74
+ test/expressions/test_11_3_2.rb
75
+ test/expressions/test_11_4_2.rb
76
+ test/expressions/test_11_4_3.rb
77
+ test/expressions/test_11_4_4.rb
78
+ test/expressions/test_11_4_5.rb
79
+ test/expressions/test_11_4_6.rb
80
+ test/expressions/test_11_4_8.rb
81
+ test/expressions/test_11_4_9.rb
82
+ test/expressions/test_11_5_1.rb
83
+ test/expressions/test_11_5_2.rb
84
+ test/expressions/test_11_5_3.rb
85
+ test/expressions/test_11_6_1-1.rb
86
+ test/expressions/test_11_9_1.rb
87
+ test/function/test_15_3_1_1-1.rb
88
+ test/global_object/test_15_1_1_1.rb
89
+ test/global_object/test_15_1_1_2.rb
90
+ test/global_object/test_15_1_1_3.rb
91
+ test/helper.rb
92
+ test/node_test_case.rb
93
+ test/object/test_15_2_1_1.rb
94
+ test/object/test_15_2_1_2.rb
95
+ test/object/test_15_2_2_1.rb
96
+ test/statements/test_12_5-1.rb
97
+ test/test_add_node.rb
98
+ test/test_arguments_node.rb
99
+ test/test_array_node.rb
100
+ test/test_assign_expr_node.rb
101
+ test/test_automatic_semicolon_insertion.rb
102
+ test/test_bit_and_node.rb
103
+ test/test_bit_or_node.rb
104
+ test/test_bit_x_or_node.rb
105
+ test/test_bitwise_not_node.rb
106
+ test/test_block_node.rb
107
+ test/test_bracket_accessor_node.rb
108
+ test/test_break_node.rb
109
+ test/test_case_block_node.rb
110
+ test/test_case_clause_node.rb
111
+ test/test_char_pos.rb
112
+ test/test_char_range.rb
113
+ test/test_comma_node.rb
114
+ test/test_comments.rb
115
+ test/test_conditional_node.rb
116
+ test/test_const_statement_node.rb
117
+ test/test_continue_node.rb
118
+ test/test_delete_node.rb
119
+ test/test_divide_node.rb
120
+ test/test_do_while_node.rb
121
+ test/test_dot_accessor_node.rb
122
+ test/test_ecma_visitor.rb
123
+ test/test_element_node.rb
124
+ test/test_empty_statement_node.rb
125
+ test/test_equal_node.rb
126
+ test/test_evaluation_visitor.rb
127
+ test/test_expression_statement_node.rb
128
+ test/test_false_node.rb
129
+ test/test_for_in_node.rb
130
+ test/test_for_node.rb
131
+ test/test_function_body_node.rb
132
+ test/test_function_call_node.rb
133
+ test/test_function_decl_node.rb
134
+ test/test_function_expr_node.rb
135
+ test/test_function_visitor.rb
136
+ test/test_getter_property_node.rb
137
+ test/test_global_object.rb
138
+ test/test_greater_node.rb
139
+ test/test_greater_or_equal_node.rb
140
+ test/test_if_node.rb
141
+ test/test_in_node.rb
142
+ test/test_instance_of_node.rb
143
+ test/test_label_node.rb
144
+ test/test_left_shift_node.rb
145
+ test/test_less_node.rb
146
+ test/test_less_or_equal_node.rb
147
+ test/test_line_number.rb
148
+ test/test_logical_and_node.rb
149
+ test/test_logical_not_node.rb
150
+ test/test_logical_or_node.rb
151
+ test/test_modulus_node.rb
152
+ test/test_multiply_node.rb
153
+ test/test_new_expr_node.rb
154
+ test/test_not_equal_node.rb
155
+ test/test_not_strict_equal_node.rb
156
+ test/test_null_node.rb
157
+ test/test_number_node.rb
158
+ test/test_object_literal_node.rb
159
+ test/test_op_and_equal_node.rb
160
+ test/test_op_divide_equal_node.rb
161
+ test/test_op_equal_node.rb
162
+ test/test_op_l_shift_equal_node.rb
163
+ test/test_op_minus_equal_node.rb
164
+ test/test_op_mod_equal_node.rb
165
+ test/test_op_multiply_equal_node.rb
166
+ test/test_op_or_equal_node.rb
167
+ test/test_op_plus_equal_node.rb
168
+ test/test_op_r_shift_equal_node.rb
169
+ test/test_op_u_r_shift_equal_node.rb
170
+ test/test_op_x_or_equal_node.rb
171
+ test/test_parameter_node.rb
172
+ test/test_parser.rb
173
+ test/test_pointcut_visitor.rb
174
+ test/test_postfix_node.rb
175
+ test/test_prefix_node.rb
176
+ test/test_property_node.rb
177
+ test/test_regexp_node.rb
178
+ test/test_resolve_node.rb
179
+ test/test_return_node.rb
180
+ test/test_right_shift_node.rb
181
+ test/test_rkelly.rb
182
+ test/test_runtime.rb
183
+ test/test_scope_chain.rb
184
+ test/test_setter_property_node.rb
185
+ test/test_source_elements.rb
186
+ test/test_strict_equal_node.rb
187
+ test/test_string_node.rb
188
+ test/test_subtract_node.rb
189
+ test/test_switch_node.rb
190
+ test/test_this_node.rb
191
+ test/test_throw_node.rb
192
+ test/test_tokenizer.rb
193
+ test/test_true_node.rb
194
+ test/test_try_node.rb
195
+ test/test_type_of_node.rb
196
+ test/test_unary_minus_node.rb
197
+ test/test_unary_plus_node.rb
198
+ test/test_unsigned_right_shift_node.rb
199
+ test/test_var_decl_node.rb
200
+ test/test_var_statement_node.rb
201
+ test/test_void_node.rb
202
+ test/test_while_node.rb
203
+ test/test_with_node.rb
data/README.rdoc ADDED
@@ -0,0 +1,135 @@
1
+ = RKelly Remix
2
+
3
+ https://github.com/nene/rkelly-remix
4
+
5
+ == DESCRIPTION
6
+
7
+ RKelly Remix is a fork of the
8
+ RKelly[https://github.com/tenderlove/rkelly] JavaScript parser.
9
+
10
+ == Install
11
+
12
+ gem install rkelly-remix
13
+
14
+ Note that you can't have rkelly and rkelly-remix both installed at the
15
+ same time. That would cause a conflict since they're both included
16
+ with:
17
+
18
+ require 'rkelly'
19
+
20
+ == Example
21
+
22
+ # Iterate over and modify a JavaScript AST. Then print the modified
23
+ # AST as JavaScript.
24
+ require 'rkelly'
25
+
26
+ parser = RKelly::Parser.new
27
+ ast = parser.parse(
28
+ "for(var i = 0; i < 10; i++) { var x = 5 + 5; }"
29
+ )
30
+
31
+ ast.each do |node|
32
+ node.value = 'hello' if node.value == 'i'
33
+ node.name = 'hello' if node.respond_to?(:name) && node.name == 'i'
34
+ end
35
+ puts ast.to_ecma # => awesome javascript
36
+
37
+ == Why fork?
38
+
39
+ Currently the original RKelly project is unmaintained. The latest
40
+ release was in late 2012, and since then the author has not responded
41
+ to bug reports or pull requests.
42
+
43
+ I created this fork mainly to satisfy the needs of my
44
+ JSDuck[https://github.com/senchalabs/jsduck] project, but you too
45
+ should consider using it, as it fixes several problems in the original
46
+ RKelly:
47
+
48
+ === Much improved speed
49
+
50
+ * 20 x faster in Ruby 1.8.
51
+ * 2 x faster in Ruby 1.9 and 2.0.
52
+
53
+ === Correct start/end position data for all syntax nodes
54
+
55
+ Original RKelly only had a rudimentary support for getting the line
56
+ number of an AST node, and even that was often wrong.
57
+
58
+ In RKelly Remix each AST node has a range property, which contains
59
+ granular data about the exact location of the node in source code:
60
+
61
+ parser = RKelly::Parser.new
62
+ ast = parser.parse(<<-eojs)
63
+ function aaron() {
64
+ var x = 10;
65
+ return 1 + 1;
66
+ }
67
+ eojs
68
+
69
+ node = ast.pointcut(ReturnNode).matches.first
70
+
71
+ node.range.to_s # <{line:3 char:5 (41)}...{line:3 char:17 (53)}>
72
+
73
+ node.range.from.line # 3
74
+ node.range.from.char # 5
75
+ node.range.from.index # 41
76
+
77
+ node.range.to.line # 3
78
+ node.range.to.char # 17
79
+ node.range.to.index # 53
80
+
81
+ === Sensible comments handling
82
+
83
+ Original RKelly attempted to associate each comment with a related AST
84
+ node, but failed to correctly do so, which is understandable, as there
85
+ is no standard way to do such a mapping. RKelly Remix abandons this
86
+ and just lists all commenst in the root node, leaving the user with
87
+ the task of associating them with AST nodes if he desires so (the same
88
+ approach is taken by another JS parser: Esprima[http://esprima.org] ).
89
+
90
+ parser = RKelly::Parser.new
91
+ ast = parser.parse(<<-eojs)
92
+ /**
93
+ * This is an awesome test comment.
94
+ */
95
+ function aaron() { // This is a side comment
96
+ var x = 10;
97
+ return 1 + 1; // Equals two!
98
+ }
99
+ eojs
100
+
101
+ # print out all the comments
102
+ ast.comments.each do |c|
103
+ puts c.value
104
+ end
105
+
106
+ === Improved parser
107
+
108
+ * List of reserved words matches with ECMAScript 5.1.
109
+ * Keywords are allowed in property names.
110
+ * Multibyte characters are supported in Ruby >= 1.9.
111
+ * Correct parsing of regexes like /[/]/
112
+
113
+ == License
114
+
115
+ The MIT License
116
+
117
+ Copyright (c) 2007, 2008, 2009 Aaron Patterson, John Barnette
118
+
119
+ Permission is hereby granted, free of charge, to any person obtaining a copy
120
+ of this software and associated documentation files (the "Software"), to deal
121
+ in the Software without restriction, including without limitation the rights
122
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
123
+ copies of the Software, and to permit persons to whom the Software is
124
+ furnished to do so, subject to the following conditions:
125
+
126
+ The above copyright notice and this permission notice shall be included in
127
+ all copies or substantial portions of the Software.
128
+
129
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
130
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
132
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
133
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
134
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
135
+ THE SOFTWARE
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+
4
+ Hoe.plugin :gemspec # `gem install hoe-gemspec`
5
+ Hoe.plugin :git # `gem install hoe-git`
6
+
7
+ GENERATED_PARSER = "lib/rkelly/generated_parser.rb"
8
+
9
+ HOE = Hoe.spec('rkelly-turbo') do |p|
10
+ license "MIT"
11
+ developer('Aaron Patterson', 'aaron.patterson@gmail.com')
12
+ developer('Rene Saarsoo', 'rene.saarsoo@sencha.com')
13
+ developer('hmdne', '54514036+hmdne@users.noreply.github.com')
14
+ self.readme_file = 'README.rdoc'
15
+ self.history_file = 'CHANGELOG.rdoc'
16
+ self.extra_rdoc_files = FileList['*.rdoc']
17
+ self.clean_globs = [GENERATED_PARSER]
18
+ end
19
+
20
+ file GENERATED_PARSER => "lib/parser.y" do |t|
21
+ if ENV['DEBUG']
22
+ sh "racc -g -v -o #{t.name} #{t.prerequisites.first}"
23
+ else
24
+ sh "racc -o #{t.name} #{t.prerequisites.first}"
25
+ end
26
+ end
27
+
28
+ task :parser => GENERATED_PARSER
29
+
30
+ # make sure the parser's up-to-date when we test
31
+ Rake::Task[:test].prerequisites << :parser
32
+ Rake::Task[:check_manifest].prerequisites << :parser
33
+
34
+ namespace :gem do
35
+ task :spec do
36
+ File.open("#{HOE.name}.gemspec", 'w') do |f|
37
+ HOE.spec.version = "#{HOE.version}.#{Time.now.strftime("%Y%m%d%H%M%S")}"
38
+ f.write(HOE.spec.to_ruby)
39
+ end
40
+ end
41
+ end
data/lib/parser.y ADDED
@@ -0,0 +1,883 @@
1
+ /* vim: set filetype=racc : */
2
+
3
+ class RKelly::GeneratedParser
4
+
5
+ /* Literals */
6
+ token NULL TRUE FALSE
7
+
8
+ /* keywords */
9
+ token BREAK CASE CATCH CONST CONTINUE DEBUGGER DEFAULT DELETE DO ELSE
10
+ token FINALLY FOR FUNCTION IF IN INSTANCEOF NEW RETURN SWITCH THIS THROW TRY
11
+ token TYPEOF VAR VOID WHILE WITH
12
+
13
+ /* reserved keywords */
14
+ token RESERVED
15
+
16
+ /* punctuators */
17
+ token EQEQ NE /* == and != */
18
+ token STREQ STRNEQ /* === and !== */
19
+ token LE GE /* < and > */
20
+ token OR AND /* || and && */
21
+ token PLUSPLUS MINUSMINUS /* ++ and -- */
22
+ token LSHIFT /* << */
23
+ token RSHIFT URSHIFT /* >> and >>> */
24
+ token PLUSEQUAL MINUSEQUAL /* += and -= */
25
+ token MULTEQUAL DIVEQUAL /* *= and /= */
26
+ token LSHIFTEQUAL /* <<= */
27
+ token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
28
+ token ANDEQUAL MODEQUAL /* &= and %= */
29
+ token XOREQUAL OREQUAL /* ^= and |= */
30
+
31
+ /* Terminal types */
32
+ token REGEXP
33
+ token NUMBER
34
+ token STRING
35
+ token IDENT
36
+
37
+ token AUTOPLUSPLUS AUTOMINUSMINUS IF_WITHOUT_ELSE
38
+
39
+ prechigh
40
+ nonassoc ELSE
41
+ nonassoc IF_WITHOUT_ELSE
42
+ preclow
43
+
44
+ rule
45
+ SourceElements:
46
+ /* nothing */ { result = SourceElementsNode.new([]) }
47
+ | SourceElementList { result = SourceElementsNode.new([val].flatten) }
48
+
49
+ SourceElementList:
50
+ SourceElement
51
+ | SourceElementList SourceElement { result = val.flatten }
52
+ ;
53
+
54
+ SourceElement:
55
+ FunctionDeclaration
56
+ | Statement
57
+ ;
58
+
59
+ Statement:
60
+ Block
61
+ | VariableStatement
62
+ | ConstStatement
63
+ | EmptyStatement
64
+ | ExprStatement
65
+ | IfStatement
66
+ | IterationStatement
67
+ | ContinueStatement
68
+ | BreakStatement
69
+ | ReturnStatement
70
+ | WithStatement
71
+ | SwitchStatement
72
+ | LabelledStatement
73
+ | ThrowStatement
74
+ | TryStatement
75
+ | DebuggerStatement
76
+ ;
77
+
78
+ Literal:
79
+ NULL { result = NullNode.new(val.first) }
80
+ | TRUE { result = TrueNode.new(val.first) }
81
+ | FALSE { result = FalseNode.new(val.first) }
82
+ | NUMBER { result = NumberNode.new(val.first) }
83
+ | STRING { result = StringNode.new(val.first) }
84
+ | REGEXP { result = RegexpNode.new(val.first) }
85
+ ;
86
+
87
+ Property:
88
+ IdentName ':' AssignmentExpr {
89
+ result = PropertyNode.new(val[0], val[2])
90
+ }
91
+ | STRING ':' AssignmentExpr { result = PropertyNode.new(val.first, val.last) }
92
+ | NUMBER ':' AssignmentExpr { result = PropertyNode.new(val.first, val.last) }
93
+ | IDENT IdentName '(' ')' FunctionBody {
94
+ klass = property_class_for(val.first)
95
+ yyabort unless klass
96
+ result = klass.new(val[1], FunctionExprNode.new(nil, val[4]))
97
+ }
98
+ | IDENT IdentName '(' FormalParameterList ')' FunctionBody {
99
+ klass = property_class_for(val.first)
100
+ yyabort unless klass
101
+ result = klass.new(val[1], FunctionExprNode.new(nil, val[5], val[3]))
102
+ }
103
+ ;
104
+
105
+ IdentName:
106
+ IDENT
107
+ | NULL | TRUE | FALSE
108
+ | BREAK | CASE | CATCH | CONST | CONTINUE | DEBUGGER | DEFAULT | DELETE | DO | ELSE
109
+ | FINALLY | FOR | FUNCTION | IF | IN | INSTANCEOF | NEW | RETURN | SWITCH | THIS | THROW | TRY
110
+ | TYPEOF | VAR | VOID | WHILE | WITH
111
+ | RESERVED
112
+ ;
113
+
114
+ PropertyList:
115
+ Property { result = val }
116
+ | PropertyList ',' Property { result = [val.first, val.last].flatten }
117
+ ;
118
+
119
+ PrimaryExpr:
120
+ PrimaryExprNoBrace
121
+ | '{' '}' { result = ObjectLiteralNode.new([]) }
122
+ | '{' PropertyList '}' { result = ObjectLiteralNode.new(val[1]) }
123
+ | '{' PropertyList ',' '}' { result = ObjectLiteralNode.new(val[1]) }
124
+ ;
125
+
126
+ PrimaryExprNoBrace:
127
+ THIS { result = ThisNode.new(val.first) }
128
+ | Literal
129
+ | ArrayLiteral
130
+ | IDENT { result = ResolveNode.new(val.first) }
131
+ | '(' Expr ')' { result = ParentheticalNode.new(val[1]) }
132
+ ;
133
+
134
+ ArrayLiteral:
135
+ '[' ElisionOpt ']' { result = ArrayNode.new([] + [nil] * val[1]) }
136
+ | '[' ElementList ']' { result = ArrayNode.new(val[1]) }
137
+ | '[' ElementList ',' ElisionOpt ']' {
138
+ result = ArrayNode.new(val[1] + [nil] * val[3])
139
+ }
140
+ ;
141
+
142
+ ElementList:
143
+ ElisionOpt AssignmentExpr {
144
+ result = [nil] * val[0] + [ElementNode.new(val[1])]
145
+ }
146
+ | ElementList ',' ElisionOpt AssignmentExpr {
147
+ result = [val[0], [nil] * val[2], ElementNode.new(val[3])].flatten
148
+ }
149
+ ;
150
+
151
+ ElisionOpt:
152
+ /* nothing */ { result = 0 }
153
+ | Elision
154
+ ;
155
+
156
+ Elision:
157
+ ',' { result = 1 }
158
+ | Elision ',' { result = val.first + 1 }
159
+ ;
160
+
161
+ MemberExpr:
162
+ PrimaryExpr
163
+ | FunctionExpr
164
+ | MemberExpr '[' Expr ']' { result = BracketAccessorNode.new(val[0], val[2]) }
165
+ | MemberExpr '.' IdentName { result = DotAccessorNode.new(val[0], val[2]) }
166
+ | NEW MemberExpr Arguments { result = NewExprNode.new(val[1], val[2]) }
167
+ ;
168
+
169
+ MemberExprNoBF:
170
+ PrimaryExprNoBrace
171
+ | MemberExprNoBF '[' Expr ']' {
172
+ result = BracketAccessorNode.new(val[0], val[2])
173
+ }
174
+ | MemberExprNoBF '.' IdentName { result = DotAccessorNode.new(val[0], val[2]) }
175
+ | NEW MemberExpr Arguments { result = NewExprNode.new(val[1], val[2]) }
176
+ ;
177
+
178
+ NewExpr:
179
+ MemberExpr
180
+ | NEW NewExpr { result = NewExprNode.new(val[1], ArgumentsNode.new([])) }
181
+ ;
182
+
183
+ NewExprNoBF:
184
+ MemberExprNoBF
185
+ | NEW NewExpr { result = NewExprNode.new(val[1], ArgumentsNode.new([])) }
186
+ ;
187
+
188
+ CallExpr:
189
+ MemberExpr Arguments { result = FunctionCallNode.new(val[0], val[1]) }
190
+ | CallExpr Arguments { result = FunctionCallNode.new(val[0], val[1]) }
191
+ | CallExpr '[' Expr ']' { result = BracketAccessorNode.new(val[0], val[2]) }
192
+ | CallExpr '.' IdentName { result = DotAccessorNode.new(val[0], val[2]) }
193
+ ;
194
+
195
+ CallExprNoBF:
196
+ VOID '(' MemberExpr ')' { result = FunctionCallNode.new(ResolveNode.new(val[0]), val[2]) }
197
+ | MemberExprNoBF Arguments { result = FunctionCallNode.new(val[0], val[1]) }
198
+ | CallExprNoBF Arguments { result = FunctionCallNode.new(val[0], val[1]) }
199
+ | CallExprNoBF '[' Expr ']' { result = BracketAccessorNode.new(val[0], val[2]) }
200
+ | CallExprNoBF '.' IdentName { result = DotAccessorNode.new(val[0], val[2]) }
201
+ ;
202
+
203
+ Arguments:
204
+ '(' ')' { result = ArgumentsNode.new([]) }
205
+ | '(' ArgumentList ')' { result = ArgumentsNode.new(val[1]); }
206
+ ;
207
+
208
+ ArgumentList:
209
+ AssignmentExpr { result = val }
210
+ | ArgumentList ',' AssignmentExpr { result = [val[0], val[2]].flatten }
211
+ ;
212
+
213
+ LeftHandSideExpr:
214
+ NewExpr
215
+ | CallExpr
216
+ ;
217
+
218
+ LeftHandSideExprNoBF:
219
+ NewExprNoBF
220
+ | CallExprNoBF
221
+ ;
222
+
223
+ PostfixExpr:
224
+ LeftHandSideExpr
225
+ | LeftHandSideExpr PLUSPLUS { result = PostfixNode.new(val[0], '++') }
226
+ | LeftHandSideExpr MINUSMINUS { result = PostfixNode.new(val[0], '--') }
227
+ ;
228
+
229
+ PostfixExprNoBF:
230
+ LeftHandSideExprNoBF
231
+ | LeftHandSideExprNoBF PLUSPLUS { result = PostfixNode.new(val[0], '++') }
232
+ | LeftHandSideExprNoBF MINUSMINUS { result = PostfixNode.new(val[0], '--') }
233
+ ;
234
+
235
+ UnaryExprCommon:
236
+ DELETE UnaryExpr { result = DeleteNode.new(val[1]) }
237
+ | VOID UnaryExpr { result = VoidNode.new(val[1]) }
238
+ | TYPEOF UnaryExpr { result = TypeOfNode.new(val[1]) }
239
+ | PLUSPLUS UnaryExpr { result = PrefixNode.new(val[1], '++') }
240
+ /* FIXME: Not sure when this can ever happen
241
+ | AUTOPLUSPLUS UnaryExpr { result = makePrefixNode($2, OpPlusPlus); } */
242
+ | MINUSMINUS UnaryExpr { result = PrefixNode.new(val[1], '--') }
243
+ /* FIXME: Not sure when this can ever happen
244
+ | AUTOMINUSMINUS UnaryExpr { result = makePrefixNode($2, OpMinusMinus); } */
245
+ | '+' UnaryExpr { result = UnaryPlusNode.new(val[1]) }
246
+ | '-' UnaryExpr { result = UnaryMinusNode.new(val[1]) }
247
+ | '~' UnaryExpr { result = BitwiseNotNode.new(val[1]) }
248
+ | '!' UnaryExpr { result = LogicalNotNode.new(val[1]) }
249
+ ;
250
+
251
+ UnaryExpr:
252
+ PostfixExpr
253
+ | UnaryExprCommon
254
+ ;
255
+
256
+ UnaryExprNoBF:
257
+ PostfixExprNoBF
258
+ | UnaryExprCommon
259
+ ;
260
+
261
+ MultiplicativeExpr:
262
+ UnaryExpr
263
+ | MultiplicativeExpr '*' UnaryExpr { result = MultiplyNode.new(val[0],val[2])}
264
+ | MultiplicativeExpr '/' UnaryExpr { result = DivideNode.new(val[0], val[2]) }
265
+ | MultiplicativeExpr '%' UnaryExpr { result = ModulusNode.new(val[0], val[2])}
266
+ ;
267
+
268
+ MultiplicativeExprNoBF:
269
+ UnaryExprNoBF
270
+ | MultiplicativeExprNoBF '*' UnaryExpr { result = MultiplyNode.new(val[0], val[2]) }
271
+ | MultiplicativeExprNoBF '/' UnaryExpr { result = DivideNode.new(val[0],val[2]) }
272
+ | MultiplicativeExprNoBF '%' UnaryExpr { result = ModulusNode.new(val[0], val[2]) }
273
+ ;
274
+
275
+ AdditiveExpr:
276
+ MultiplicativeExpr
277
+ | AdditiveExpr '+' MultiplicativeExpr { result = AddNode.new(val[0], val[2]) }
278
+ | AdditiveExpr '-' MultiplicativeExpr { result = SubtractNode.new(val[0], val[2]) }
279
+ ;
280
+
281
+ AdditiveExprNoBF:
282
+ MultiplicativeExprNoBF
283
+ | AdditiveExprNoBF '+' MultiplicativeExpr { result = AddNode.new(val[0], val[2]) }
284
+ | AdditiveExprNoBF '-' MultiplicativeExpr { result = SubtractNode.new(val[0], val[2]) }
285
+ ;
286
+
287
+ ShiftExpr:
288
+ AdditiveExpr
289
+ | ShiftExpr LSHIFT AdditiveExpr { result = LeftShiftNode.new(val[0], val[2]) }
290
+ | ShiftExpr RSHIFT AdditiveExpr { result = RightShiftNode.new(val[0], val[2]) }
291
+ | ShiftExpr URSHIFT AdditiveExpr { result = UnsignedRightShiftNode.new(val[0], val[2]) }
292
+ ;
293
+
294
+ ShiftExprNoBF:
295
+ AdditiveExprNoBF
296
+ | ShiftExprNoBF LSHIFT AdditiveExpr { result = LeftShiftNode.new(val[0], val[2]) }
297
+ | ShiftExprNoBF RSHIFT AdditiveExpr { result = RightShiftNode.new(val[0], val[2]) }
298
+ | ShiftExprNoBF URSHIFT AdditiveExpr { result = UnsignedRightShiftNode.new(val[0], val[2]) }
299
+ ;
300
+
301
+ RelationalExpr:
302
+ ShiftExpr
303
+ | RelationalExpr '<' ShiftExpr { result = LessNode.new(val[0], val[2])}
304
+ | RelationalExpr '>' ShiftExpr { result = GreaterNode.new(val[0], val[2]) }
305
+ | RelationalExpr LE ShiftExpr { result = LessOrEqualNode.new(val[0], val[2]) }
306
+ | RelationalExpr GE ShiftExpr { result = GreaterOrEqualNode.new(val[0], val[2]) }
307
+ | RelationalExpr INSTANCEOF ShiftExpr { result = InstanceOfNode.new(val[0], val[2]) }
308
+ | RelationalExpr IN ShiftExpr { result = InNode.new(val[0], val[2]) }
309
+ ;
310
+
311
+ RelationalExprNoIn:
312
+ ShiftExpr
313
+ | RelationalExprNoIn '<' ShiftExpr { result = LessNode.new(val[0], val[2])}
314
+ | RelationalExprNoIn '>' ShiftExpr { result = GreaterNode.new(val[0], val[2]) }
315
+ | RelationalExprNoIn LE ShiftExpr { result = LessOrEqualNode.new(val[0], val[2]) }
316
+ | RelationalExprNoIn GE ShiftExpr { result = GreaterOrEqualNode.new(val[0], val[2]) }
317
+ | RelationalExprNoIn INSTANCEOF ShiftExpr
318
+ { result = InstanceOfNode.new(val[0], val[2]) }
319
+ ;
320
+
321
+ RelationalExprNoBF:
322
+ ShiftExprNoBF
323
+ | RelationalExprNoBF '<' ShiftExpr { result = LessNode.new(val[0], val[2]) }
324
+ | RelationalExprNoBF '>' ShiftExpr { result = GreaterNode.new(val[0], val[2]) }
325
+ | RelationalExprNoBF LE ShiftExpr { result = LessOrEqualNode.new(val[0], val[2]) }
326
+ | RelationalExprNoBF GE ShiftExpr { result = GreaterOrEqualNode.new(val[0], val[2]) }
327
+ | RelationalExprNoBF INSTANCEOF ShiftExpr
328
+ { result = InstanceOfNode.new(val[0], val[2]) }
329
+ | RelationalExprNoBF IN ShiftExpr { result = InNode.new(val[0], val[2]) }
330
+ ;
331
+
332
+ EqualityExpr:
333
+ RelationalExpr
334
+ | EqualityExpr EQEQ RelationalExpr { result = EqualNode.new(val[0], val[2]) }
335
+ | EqualityExpr NE RelationalExpr { result = NotEqualNode.new(val[0], val[2]) }
336
+ | EqualityExpr STREQ RelationalExpr { result = StrictEqualNode.new(val[0], val[2]) }
337
+ | EqualityExpr STRNEQ RelationalExpr { result = NotStrictEqualNode.new(val[0], val[2]) }
338
+ ;
339
+
340
+ EqualityExprNoIn:
341
+ RelationalExprNoIn
342
+ | EqualityExprNoIn EQEQ RelationalExprNoIn
343
+ { result = EqualNode.new(val[0], val[2]) }
344
+ | EqualityExprNoIn NE RelationalExprNoIn
345
+ { result = NotEqualNode.new(val[0], val[2]) }
346
+ | EqualityExprNoIn STREQ RelationalExprNoIn
347
+ { result = StrictEqualNode.new(val[0], val[2]) }
348
+ | EqualityExprNoIn STRNEQ RelationalExprNoIn
349
+ { result = NotStrictEqualNode.new(val[0], val[2]) }
350
+ ;
351
+
352
+ EqualityExprNoBF:
353
+ RelationalExprNoBF
354
+ | EqualityExprNoBF EQEQ RelationalExpr
355
+ { result = EqualNode.new(val[0], val[2]) }
356
+ | EqualityExprNoBF NE RelationalExpr { result = NotEqualNode.new(val[0], val[2]) }
357
+ | EqualityExprNoBF STREQ RelationalExpr
358
+ { result = StrictEqualNode.new(val[0], val[2]) }
359
+ | EqualityExprNoBF STRNEQ RelationalExpr
360
+ { result = NotStrictEqualNode.new(val[0], val[2]) }
361
+ ;
362
+
363
+ BitwiseANDExpr:
364
+ EqualityExpr
365
+ | BitwiseANDExpr '&' EqualityExpr { result = BitAndNode.new(val[0], val[2]) }
366
+ ;
367
+
368
+ BitwiseANDExprNoIn:
369
+ EqualityExprNoIn
370
+ | BitwiseANDExprNoIn '&' EqualityExprNoIn
371
+ { result = BitAndNode.new(val[0], val[2]) }
372
+ ;
373
+
374
+ BitwiseANDExprNoBF:
375
+ EqualityExprNoBF
376
+ | BitwiseANDExprNoBF '&' EqualityExpr { result = BitAndNode.new(val[0], val[2]) }
377
+ ;
378
+
379
+ BitwiseXORExpr:
380
+ BitwiseANDExpr
381
+ | BitwiseXORExpr '^' BitwiseANDExpr { result = BitXOrNode.new(val[0], val[2]) }
382
+ ;
383
+
384
+ BitwiseXORExprNoIn:
385
+ BitwiseANDExprNoIn
386
+ | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
387
+ { result = BitXOrNode.new(val[0], val[2]) }
388
+ ;
389
+
390
+ BitwiseXORExprNoBF:
391
+ BitwiseANDExprNoBF
392
+ | BitwiseXORExprNoBF '^' BitwiseANDExpr
393
+ { result = BitXOrNode.new(val[0], val[2]) }
394
+ ;
395
+
396
+ BitwiseORExpr:
397
+ BitwiseXORExpr
398
+ | BitwiseORExpr '|' BitwiseXORExpr { result = BitOrNode.new(val[0], val[2]) }
399
+ ;
400
+
401
+ BitwiseORExprNoIn:
402
+ BitwiseXORExprNoIn
403
+ | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
404
+ { result = BitOrNode.new(val[0], val[2]) }
405
+ ;
406
+
407
+ BitwiseORExprNoBF:
408
+ BitwiseXORExprNoBF
409
+ | BitwiseORExprNoBF '|' BitwiseXORExpr
410
+ { result = BitOrNode.new(val[0], val[2]) }
411
+ ;
412
+
413
+ LogicalANDExpr:
414
+ BitwiseORExpr
415
+ | LogicalANDExpr AND BitwiseORExpr { result = LogicalAndNode.new(val[0], val[2]) }
416
+ ;
417
+
418
+ LogicalANDExprNoIn:
419
+ BitwiseORExprNoIn
420
+ | LogicalANDExprNoIn AND BitwiseORExprNoIn
421
+ { result = LogicalAndNode.new(val[0], val[2]) }
422
+ ;
423
+
424
+ LogicalANDExprNoBF:
425
+ BitwiseORExprNoBF
426
+ | LogicalANDExprNoBF AND BitwiseORExpr
427
+ { result = LogicalAndNode.new(val[0], val[2]) }
428
+ ;
429
+
430
+ LogicalORExpr:
431
+ LogicalANDExpr
432
+ | LogicalORExpr OR LogicalANDExpr { result = LogicalOrNode.new(val[0], val[2]) }
433
+ ;
434
+
435
+ LogicalORExprNoIn:
436
+ LogicalANDExprNoIn
437
+ | LogicalORExprNoIn OR LogicalANDExprNoIn
438
+ { result = LogicalOrNode.new(val[0], val[2]) }
439
+ ;
440
+
441
+ LogicalORExprNoBF:
442
+ LogicalANDExprNoBF
443
+ | LogicalORExprNoBF OR LogicalANDExpr { result = LogicalOrNode.new(val[0], val[2]) }
444
+ ;
445
+
446
+ ConditionalExpr:
447
+ LogicalORExpr
448
+ | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr {
449
+ result = ConditionalNode.new(val[0], val[2], val[4])
450
+ }
451
+ ;
452
+
453
+ ConditionalExprNoIn:
454
+ LogicalORExprNoIn
455
+ | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn {
456
+ result = ConditionalNode.new(val[0], val[2], val[4])
457
+ }
458
+ ;
459
+
460
+ ConditionalExprNoBF:
461
+ LogicalORExprNoBF
462
+ | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr {
463
+ result = ConditionalNode.new(val[0], val[2], val[4])
464
+ }
465
+ ;
466
+
467
+ AssignmentExpr:
468
+ ConditionalExpr
469
+ | LeftHandSideExpr AssignmentOperator AssignmentExpr {
470
+ result = val[1].new(val.first, val.last)
471
+ }
472
+ ;
473
+
474
+ AssignmentExprNoIn:
475
+ ConditionalExprNoIn
476
+ | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn {
477
+ result = val[1].new(val.first, val.last)
478
+ }
479
+ ;
480
+
481
+ AssignmentExprNoBF:
482
+ ConditionalExprNoBF
483
+ | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr {
484
+ result = val[1].new(val.first, val.last)
485
+ }
486
+ ;
487
+
488
+ AssignmentOperator:
489
+ '=' { result = OpEqualNode }
490
+ | PLUSEQUAL { result = OpPlusEqualNode }
491
+ | MINUSEQUAL { result = OpMinusEqualNode }
492
+ | MULTEQUAL { result = OpMultiplyEqualNode }
493
+ | DIVEQUAL { result = OpDivideEqualNode }
494
+ | LSHIFTEQUAL { result = OpLShiftEqualNode }
495
+ | RSHIFTEQUAL { result = OpRShiftEqualNode }
496
+ | URSHIFTEQUAL { result = OpURShiftEqualNode }
497
+ | ANDEQUAL { result = OpAndEqualNode }
498
+ | XOREQUAL { result = OpXOrEqualNode }
499
+ | OREQUAL { result = OpOrEqualNode }
500
+ | MODEQUAL { result = OpModEqualNode }
501
+ ;
502
+
503
+ Expr:
504
+ AssignmentExpr
505
+ | Expr ',' AssignmentExpr { result = CommaNode.new(val[0], val[2]) }
506
+ ;
507
+
508
+ ExprNoIn:
509
+ AssignmentExprNoIn
510
+ | ExprNoIn ',' AssignmentExprNoIn { result = CommaNode.new(val[0], val[2]) }
511
+ ;
512
+
513
+ ExprNoBF:
514
+ AssignmentExprNoBF
515
+ | ExprNoBF ',' AssignmentExpr { result = CommaNode.new(val[0], val[2]) }
516
+ ;
517
+
518
+
519
+ Block:
520
+ '{' SourceElements '}' {
521
+ result = BlockNode.new(val[1])
522
+ debug(result)
523
+ }
524
+ ;
525
+
526
+ VariableStatement:
527
+ VAR VariableDeclarationList ';' {
528
+ result = VarStatementNode.new(val[1])
529
+ debug(result)
530
+ }
531
+ | VAR VariableDeclarationList error {
532
+ result = VarStatementNode.new(val[1])
533
+ debug(result)
534
+ yyabort unless allow_auto_semi?(val.last)
535
+ }
536
+ ;
537
+
538
+ VariableDeclarationList:
539
+ VariableDeclaration { result = val }
540
+ | VariableDeclarationList ',' VariableDeclaration {
541
+ result = [val.first, val.last].flatten
542
+ }
543
+ ;
544
+
545
+ VariableDeclarationListNoIn:
546
+ VariableDeclarationNoIn { result = val }
547
+ | VariableDeclarationListNoIn ',' VariableDeclarationNoIn {
548
+ result = [val.first, val.last].flatten
549
+ }
550
+ ;
551
+
552
+ VariableDeclaration:
553
+ IDENT { result = VarDeclNode.new(val.first, nil) }
554
+ | IDENT Initializer { result = VarDeclNode.new(val.first, val[1]) }
555
+ ;
556
+
557
+ VariableDeclarationNoIn:
558
+ IDENT { result = VarDeclNode.new(val[0],nil) }
559
+ | IDENT InitializerNoIn { result = VarDeclNode.new(val[0], val[1]) }
560
+ ;
561
+
562
+ ConstStatement:
563
+ CONST ConstDeclarationList ';' {
564
+ result = ConstStatementNode.new(val[1])
565
+ debug(result)
566
+ }
567
+ | CONST ConstDeclarationList error {
568
+ result = ConstStatementNode.new(val[1])
569
+ debug(result)
570
+ yyerror unless allow_auto_semi?(val.last)
571
+ }
572
+ ;
573
+
574
+ ConstDeclarationList:
575
+ ConstDeclaration { result = val }
576
+ | ConstDeclarationList ',' ConstDeclaration {
577
+ result = [val.first, val.last].flatten
578
+ }
579
+ ;
580
+
581
+ ConstDeclaration:
582
+ IDENT { result = VarDeclNode.new(val[0], nil, true) }
583
+ | IDENT Initializer { result = VarDeclNode.new(val[0], val[1], true) }
584
+ ;
585
+
586
+ Initializer:
587
+ '=' AssignmentExpr { result = AssignExprNode.new(val[1]) }
588
+ ;
589
+
590
+ InitializerNoIn:
591
+ '=' AssignmentExprNoIn { result = AssignExprNode.new(val[1]) }
592
+ ;
593
+
594
+ EmptyStatement:
595
+ ';' { result = EmptyStatementNode.new(val[0]) }
596
+ ;
597
+
598
+ ExprStatement:
599
+ ExprNoBF ';' {
600
+ result = ExpressionStatementNode.new(val.first)
601
+ debug(result)
602
+ }
603
+ | ExprNoBF error {
604
+ result = ExpressionStatementNode.new(val.first)
605
+ debug(result)
606
+ raise RKelly::SyntaxError unless allow_auto_semi?(val.last)
607
+ }
608
+ ;
609
+
610
+ IfStatement:
611
+ IF '(' Expr ')' Statement =IF_WITHOUT_ELSE {
612
+ result = IfNode.new(val[2], val[4])
613
+ debug(result)
614
+ }
615
+ | IF '(' Expr ')' Statement ELSE Statement {
616
+ result = IfNode.new(val[2], val[4], val[6])
617
+ debug(result)
618
+ }
619
+ ;
620
+
621
+ IterationStatement:
622
+ DO Statement WHILE '(' Expr ')' ';' {
623
+ result = DoWhileNode.new(val[1], val[4])
624
+ debug(result)
625
+ }
626
+ | DO Statement WHILE '(' Expr ')' error {
627
+ result = DoWhileNode.new(val[1], val[4])
628
+ debug(result)
629
+ } /* Always performs automatic semicolon insertion. */
630
+ | WHILE '(' Expr ')' Statement {
631
+ result = WhileNode.new(val[2], val[4])
632
+ debug(result)
633
+ }
634
+ | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement {
635
+ result = ForNode.new(val[2], val[4], val[6], val[8])
636
+ debug(result)
637
+ }
638
+ | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
639
+ {
640
+ result = ForNode.new(VarStatementNode.new(val[3]), val[5], val[7], val[9])
641
+ debug(result)
642
+ }
643
+ | FOR '(' LeftHandSideExpr IN Expr ')' Statement {
644
+ #yyabort if (!n.isLocation())
645
+ result = ForInNode.new(val[2], val[4], val[6])
646
+ debug(result);
647
+ }
648
+ | FOR '(' VAR IDENT IN Expr ')' Statement {
649
+ result = ForInNode.new(
650
+ VarDeclNode.new(val[3], nil), val[5], val[7])
651
+ debug(result)
652
+ }
653
+ | FOR '(' VAR IDENT InitializerNoIn IN Expr ')' Statement {
654
+ result = ForInNode.new(
655
+ VarDeclNode.new(val[3], val[4]), val[6], val[8]
656
+ )
657
+ debug(result)
658
+ }
659
+ ;
660
+
661
+ ExprOpt:
662
+ /* nothing */ { result = nil }
663
+ | Expr
664
+ ;
665
+
666
+ ExprNoInOpt:
667
+ /* nothing */ { result = nil }
668
+ | ExprNoIn
669
+ ;
670
+
671
+ ContinueStatement:
672
+ CONTINUE ';' {
673
+ result = ContinueNode.new(nil)
674
+ debug(result)
675
+ }
676
+ | CONTINUE error {
677
+ result = ContinueNode.new(nil)
678
+ debug(result)
679
+ yyabort unless allow_auto_semi?(val[1])
680
+ }
681
+ | CONTINUE IDENT ';' {
682
+ result = ContinueNode.new(val[1])
683
+ debug(result)
684
+ }
685
+ | CONTINUE IDENT error {
686
+ result = ContinueNode.new(val[1])
687
+ debug(result)
688
+ yyabort unless allow_auto_semi?(val[2])
689
+ }
690
+ ;
691
+
692
+ BreakStatement:
693
+ BREAK ';' {
694
+ result = BreakNode.new(nil)
695
+ debug(result)
696
+ }
697
+ | BREAK error {
698
+ result = BreakNode.new(nil)
699
+ debug(result)
700
+ yyabort unless allow_auto_semi?(val[1])
701
+ }
702
+ | BREAK IDENT ';' {
703
+ result = BreakNode.new(val[1])
704
+ debug(result)
705
+ }
706
+ | BREAK IDENT error {
707
+ result = BreakNode.new(val[1])
708
+ debug(result)
709
+ yyabort unless allow_auto_semi?(val[2])
710
+ }
711
+ ;
712
+
713
+ ReturnStatement:
714
+ RETURN ';' {
715
+ result = ReturnNode.new(nil)
716
+ debug(result)
717
+ }
718
+ | RETURN error {
719
+ result = ReturnNode.new(nil)
720
+ debug(result)
721
+ yyabort unless allow_auto_semi?(val[1])
722
+ }
723
+ | RETURN Expr ';' {
724
+ result = ReturnNode.new(val[1])
725
+ debug(result)
726
+ }
727
+ | RETURN Expr error {
728
+ result = ReturnNode.new(val[1])
729
+ debug(result)
730
+ yyabort unless allow_auto_semi?(val[2])
731
+ }
732
+ ;
733
+
734
+ WithStatement:
735
+ WITH '(' Expr ')' Statement {
736
+ result = WithNode.new(val[2], val[4])
737
+ debug(result)
738
+ }
739
+ ;
740
+
741
+ SwitchStatement:
742
+ SWITCH '(' Expr ')' CaseBlock {
743
+ result = SwitchNode.new(val[2], val[4])
744
+ debug(result)
745
+ }
746
+ ;
747
+
748
+ CaseBlock:
749
+ '{' CaseClausesOpt '}' { result = CaseBlockNode.new(val[1]) }
750
+ | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}' {
751
+ result = CaseBlockNode.new([val[1], val[2], val[3]].flatten)
752
+ }
753
+ ;
754
+
755
+ CaseClausesOpt:
756
+ /* nothing */ { result = [] }
757
+ | CaseClauses
758
+ ;
759
+
760
+ CaseClauses:
761
+ CaseClause { result = val }
762
+ | CaseClauses CaseClause { result = val.flatten }
763
+ ;
764
+
765
+ CaseClause:
766
+ CASE Expr ':' SourceElements {
767
+ result = CaseClauseNode.new(val[1], val[3])
768
+ }
769
+ ;
770
+
771
+ DefaultClause:
772
+ DEFAULT ':' SourceElements {
773
+ result = CaseClauseNode.new(nil, val[2])
774
+ }
775
+ ;
776
+
777
+ LabelledStatement:
778
+ IDENT ':' Statement { result = LabelNode.new(val[0], val[2]) }
779
+ ;
780
+
781
+ ThrowStatement:
782
+ THROW Expr ';' {
783
+ result = ThrowNode.new(val[1])
784
+ debug(result)
785
+ }
786
+ | THROW Expr error {
787
+ result = ThrowNode.new(val[1])
788
+ debug(result)
789
+ yyabort unless allow_auto_semi?(val[2])
790
+ }
791
+ ;
792
+
793
+ TryStatement:
794
+ TRY Block FINALLY Block {
795
+ result = TryNode.new(val[1], nil, nil, val[3])
796
+ debug(result)
797
+ }
798
+ | TRY Block CATCH '(' IDENT ')' Block {
799
+ result = TryNode.new(val[1], val[4], val[6])
800
+ debug(result)
801
+ }
802
+ | TRY Block CATCH '(' IDENT ')' Block FINALLY Block {
803
+ result = TryNode.new(val[1], val[4], val[6], val[8])
804
+ debug(result)
805
+ }
806
+ ;
807
+
808
+ DebuggerStatement:
809
+ DEBUGGER ';' {
810
+ result = EmptyStatementNode.new(val[0])
811
+ debug(result)
812
+ }
813
+ | DEBUGGER error {
814
+ result = EmptyStatementNode.new(val[0])
815
+ debug(result)
816
+ yyabort unless allow_auto_semi?(val[1])
817
+ }
818
+ ;
819
+
820
+ FunctionDeclaration:
821
+ FUNCTION IDENT '(' ')' FunctionBody {
822
+ result = FunctionDeclNode.new(val[1], val[4])
823
+ debug(val[5])
824
+ }
825
+ | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody {
826
+ result = FunctionDeclNode.new(val[1], val[5], val[3])
827
+ debug(val[6])
828
+ }
829
+ ;
830
+
831
+ FunctionExpr:
832
+ FUNCTION '(' ')' FunctionBody {
833
+ result = FunctionExprNode.new(val[0], val[3])
834
+ debug(val[4])
835
+ }
836
+ | FUNCTION '(' FormalParameterList ')' FunctionBody {
837
+ result = FunctionExprNode.new(val[0], val[4], val[2])
838
+ debug(val[5])
839
+ }
840
+ | FUNCTION IDENT '(' ')' FunctionBody {
841
+ result = FunctionExprNode.new(val[1], val[4])
842
+ debug(val[5])
843
+ }
844
+ | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody {
845
+ result = FunctionExprNode.new(val[1], val[5], val[3])
846
+ debug(val[6])
847
+ }
848
+ ;
849
+
850
+ FormalParameterList:
851
+ IDENT { result = [ParameterNode.new(val[0])] }
852
+ | FormalParameterList ',' IDENT {
853
+ result = [val.first, ParameterNode.new(val.last)].flatten
854
+ }
855
+ ;
856
+
857
+ FunctionBody:
858
+ '{' SourceElements '}' { result = FunctionBodyNode.new(val[1]) }
859
+ ;
860
+ end
861
+
862
+ ---- header
863
+ require "rkelly/nodes"
864
+
865
+ ---- inner
866
+ include RKelly::Nodes
867
+
868
+ def allow_auto_semi?(error_token)
869
+ error_token == false || error_token == '}' || @terminator
870
+ end
871
+
872
+ def property_class_for(ident)
873
+ case ident
874
+ when 'get'
875
+ GetterPropertyNode
876
+ when 'set'
877
+ SetterPropertyNode
878
+ end
879
+ end
880
+
881
+ def debug(*args)
882
+ logger.debug(*args) if logger
883
+ end