rkelly-turbo 0.1.0

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