rattler 0.5.0 → 0.6.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 (329) hide show
  1. data/README.rdoc +3 -175
  2. data/features/README.markdown +27 -0
  3. data/features/Tutorial.md +224 -0
  4. data/features/command_line/output_option.feature +2 -1
  5. data/features/command_line/{parser_generator.feature → rtlr.feature} +43 -15
  6. data/features/error_reporting/automatic_error_messages.feature +40 -0
  7. data/features/error_reporting/custom_error_messages.feature +28 -0
  8. data/features/examples/json_parser.markdown +88 -0
  9. data/features/{grammar → extended_matching_syntax}/back_reference.feature +5 -3
  10. data/features/{grammar → extended_matching_syntax}/e_symbol.feature +2 -2
  11. data/features/{grammar → extended_matching_syntax}/eof.feature +4 -3
  12. data/features/{grammar → extended_matching_syntax}/fail.feature +8 -6
  13. data/features/extended_matching_syntax/fragments.feature +29 -0
  14. data/features/extended_matching_syntax/include.feature +42 -0
  15. data/features/{grammar → extended_matching_syntax}/list_matching.feature +7 -6
  16. data/features/extended_matching_syntax/posix_class.feature +127 -0
  17. data/features/{grammar → extended_matching_syntax}/repeat.feature +29 -3
  18. data/features/{grammar → extended_matching_syntax}/skip_operator.feature +2 -1
  19. data/features/extended_matching_syntax/super.feature +24 -0
  20. data/features/{grammar → extended_matching_syntax}/token.feature +6 -5
  21. data/features/{grammar → extended_matching_syntax}/whitespace.feature +7 -6
  22. data/features/{grammar → extended_matching_syntax}/word_literal.feature +10 -6
  23. data/features/grammar_heading/explicit_start_rule.feature +20 -0
  24. data/features/grammar_heading/grammar_declaration.feature +60 -0
  25. data/features/grammar_heading/include.feature +19 -0
  26. data/features/grammar_heading/require.feature +27 -0
  27. data/features/{grammar → peg_syntax}/any_character.feature +1 -1
  28. data/features/peg_syntax/character_class.feature +25 -0
  29. data/features/{grammar → peg_syntax}/comments.feature +1 -1
  30. data/features/{grammar → peg_syntax}/literal.feature +5 -3
  31. data/features/{grammar → peg_syntax}/negative_lookahead.feature +5 -3
  32. data/features/peg_syntax/nonterminal.feature +46 -0
  33. data/features/peg_syntax/one_or_more.feature +59 -0
  34. data/features/{grammar → peg_syntax}/optional.feature +2 -2
  35. data/features/peg_syntax/ordered_choice.feature +24 -0
  36. data/features/{grammar → peg_syntax}/positive_lookahead.feature +6 -4
  37. data/features/peg_syntax/sequence.feature +23 -0
  38. data/features/{grammar → peg_syntax}/start_rule.feature +1 -1
  39. data/features/peg_syntax/zero_or_more.feature +59 -0
  40. data/features/{grammar → semantics}/labels.feature +0 -0
  41. data/features/{grammar → semantics}/negative_semantic_predicate.feature +30 -9
  42. data/features/{grammar → semantics}/node_action.feature +0 -0
  43. data/features/{grammar → semantics}/positive_semantic_predicate.feature +29 -8
  44. data/features/{grammar/symantic_action.feature → semantics/semantic_action.feature} +2 -2
  45. data/features/semantics/semantic_result.feature +86 -0
  46. data/features/{grammar → semantics}/side_effect.feature +33 -21
  47. data/features/step_definitions/cli_steps.rb +1 -1
  48. data/features/step_definitions/grammar_steps.rb +19 -5
  49. data/features/support/env.rb +5 -0
  50. data/lib/rattler.rb +21 -44
  51. data/lib/rattler/compiler.rb +69 -0
  52. data/lib/rattler/{grammar → compiler}/grammar_parser.rb +58 -24
  53. data/lib/rattler/compiler/metagrammar.rb +1570 -0
  54. data/lib/rattler/compiler/optimizer.rb +77 -0
  55. data/lib/rattler/{back_end → compiler}/optimizer/composite_reducing.rb +2 -2
  56. data/lib/rattler/{back_end → compiler}/optimizer/flatten_choice.rb +3 -12
  57. data/lib/rattler/{back_end → compiler}/optimizer/flatten_sequence.rb +4 -16
  58. data/lib/rattler/{back_end → compiler}/optimizer/flattening.rb +2 -2
  59. data/lib/rattler/compiler/optimizer/inline_regular_rules.rb +24 -0
  60. data/lib/rattler/{back_end → compiler}/optimizer/join_match_capturing_sequence.rb +16 -14
  61. data/lib/rattler/{back_end → compiler}/optimizer/join_match_choice.rb +4 -13
  62. data/lib/rattler/{back_end → compiler}/optimizer/join_match_matching_sequence.rb +4 -13
  63. data/lib/rattler/compiler/optimizer/join_match_sequence.rb +7 -0
  64. data/lib/rattler/{back_end → compiler}/optimizer/join_predicate_bare_match.rb +3 -12
  65. data/lib/rattler/compiler/optimizer/join_predicate_match.rb +7 -0
  66. data/lib/rattler/{back_end → compiler}/optimizer/join_predicate_nested_match.rb +4 -13
  67. data/lib/rattler/{back_end → compiler}/optimizer/join_predicate_or_bare_match.rb +3 -12
  68. data/lib/rattler/compiler/optimizer/join_predicate_or_match.rb +7 -0
  69. data/lib/rattler/{back_end → compiler}/optimizer/join_predicate_or_nested_match.rb +4 -13
  70. data/lib/rattler/{back_end → compiler}/optimizer/match_joining.rb +2 -2
  71. data/lib/rattler/{back_end → compiler}/optimizer/optimization.rb +12 -34
  72. data/lib/rattler/compiler/optimizer/optimization_context.rb +83 -0
  73. data/lib/rattler/{back_end → compiler}/optimizer/optimization_sequence.rb +3 -11
  74. data/lib/rattler/compiler/optimizer/optimizations.rb +27 -0
  75. data/lib/rattler/{back_end → compiler}/optimizer/optimize_children.rb +6 -14
  76. data/lib/rattler/{back_end → compiler}/optimizer/reduce_repeat_match.rb +4 -13
  77. data/lib/rattler/compiler/optimizer/remove_meaningless_wrapper.rb +22 -0
  78. data/lib/rattler/{back_end → compiler}/optimizer/simplify_redundant_repeat.rb +4 -13
  79. data/lib/rattler/{back_end → compiler}/optimizer/simplify_token_match.rb +4 -13
  80. data/lib/rattler/compiler/parser_generator.rb +108 -0
  81. data/lib/rattler/{back_end → compiler}/parser_generator/apply_generator.rb +7 -21
  82. data/lib/rattler/{back_end → compiler}/parser_generator/assert_generator.rb +11 -19
  83. data/lib/rattler/compiler/parser_generator/attributed_sequence_generator.rb +37 -0
  84. data/lib/rattler/{back_end → compiler}/parser_generator/back_reference_generator.rb +10 -10
  85. data/lib/rattler/{back_end → compiler}/parser_generator/choice_generator.rb +10 -22
  86. data/lib/rattler/{back_end → compiler}/parser_generator/delegating_generator.rb +2 -2
  87. data/lib/rattler/{back_end → compiler}/parser_generator/disallow_generator.rb +11 -19
  88. data/lib/rattler/{back_end → compiler}/parser_generator/e_symbol_generator.rb +2 -10
  89. data/lib/rattler/{back_end → compiler}/parser_generator/eof_generator.rb +2 -10
  90. data/lib/rattler/{back_end → compiler}/parser_generator/expr_generator.rb +9 -35
  91. data/lib/rattler/{back_end → compiler}/parser_generator/fail_generator.rb +7 -3
  92. data/lib/rattler/{back_end → compiler}/parser_generator/gen_method_names.rb +3 -5
  93. data/lib/rattler/{back_end → compiler}/parser_generator/general_list_generator.rb +6 -18
  94. data/lib/rattler/{back_end → compiler}/parser_generator/general_repeat_generator.rb +16 -22
  95. data/lib/rattler/{back_end/parser_generator/rule_set_generator.rb → compiler/parser_generator/grammar_generator.rb} +24 -33
  96. data/lib/rattler/compiler/parser_generator/group_match.rb +33 -0
  97. data/lib/rattler/{back_end → compiler}/parser_generator/group_match_generator.rb +4 -17
  98. data/lib/rattler/compiler/parser_generator/label_generator.rb +37 -0
  99. data/lib/rattler/{back_end → compiler}/parser_generator/list0_generating.rb +5 -5
  100. data/lib/rattler/{back_end → compiler}/parser_generator/list1_generating.rb +3 -3
  101. data/lib/rattler/{back_end → compiler}/parser_generator/list_generator.rb +2 -2
  102. data/lib/rattler/{back_end → compiler}/parser_generator/match_generator.rb +10 -10
  103. data/lib/rattler/{back_end → compiler}/parser_generator/nested.rb +2 -2
  104. data/lib/rattler/compiler/parser_generator/node_action_generator.rb +49 -0
  105. data/lib/rattler/{back_end → compiler}/parser_generator/one_or_more_generating.rb +3 -3
  106. data/lib/rattler/{back_end → compiler}/parser_generator/optional_generating.rb +6 -22
  107. data/lib/rattler/compiler/parser_generator/predicate_propogating.rb +24 -0
  108. data/lib/rattler/{back_end → compiler}/parser_generator/repeat_generator.rb +2 -2
  109. data/lib/rattler/compiler/parser_generator/rule_generator.rb +66 -0
  110. data/lib/rattler/compiler/parser_generator/rule_set_generator.rb +33 -0
  111. data/lib/rattler/compiler/parser_generator/semantic_action_generator.rb +58 -0
  112. data/lib/rattler/compiler/parser_generator/sequence_generating.rb +138 -0
  113. data/lib/rattler/compiler/parser_generator/sequence_generator.rb +57 -0
  114. data/lib/rattler/{back_end → compiler}/parser_generator/skip_generator.rb +4 -18
  115. data/lib/rattler/compiler/parser_generator/skip_propogating.rb +16 -0
  116. data/lib/rattler/{back_end → compiler}/parser_generator/sub_generating.rb +19 -11
  117. data/lib/rattler/compiler/parser_generator/super_generator.rb +54 -0
  118. data/lib/rattler/{back_end → compiler}/parser_generator/token_generator.rb +3 -3
  119. data/lib/rattler/compiler/parser_generator/token_propogating.rb +10 -0
  120. data/lib/rattler/{back_end → compiler}/parser_generator/top_level.rb +2 -2
  121. data/lib/rattler/{back_end → compiler}/parser_generator/zero_or_more_generating.rb +5 -5
  122. data/lib/rattler/compiler/rattler.rtlr +201 -0
  123. data/lib/rattler/{back_end → compiler}/ruby_generator.rb +16 -25
  124. data/lib/rattler/parsers.rb +12 -33
  125. data/lib/rattler/parsers/action_code.rb +25 -16
  126. data/lib/rattler/{grammar → parsers}/analysis.rb +32 -11
  127. data/lib/rattler/parsers/apply.rb +10 -19
  128. data/lib/rattler/parsers/assert.rb +4 -14
  129. data/lib/rattler/parsers/atomic.rb +3 -10
  130. data/lib/rattler/parsers/attributed_sequence.rb +50 -0
  131. data/lib/rattler/parsers/back_reference.rb +19 -14
  132. data/lib/rattler/parsers/choice.rb +11 -12
  133. data/lib/rattler/parsers/combinator_parser.rb +15 -7
  134. data/lib/rattler/parsers/combining.rb +15 -9
  135. data/lib/rattler/parsers/disallow.rb +5 -12
  136. data/lib/rattler/parsers/e_symbol.rb +5 -14
  137. data/lib/rattler/parsers/eof.rb +10 -15
  138. data/lib/rattler/parsers/fail.rb +16 -26
  139. data/lib/rattler/{grammar → parsers}/grammar.rb +15 -20
  140. data/lib/rattler/parsers/label.rb +10 -16
  141. data/lib/rattler/parsers/list_parser.rb +14 -14
  142. data/lib/rattler/parsers/match.rb +5 -17
  143. data/lib/rattler/parsers/node_action.rb +72 -0
  144. data/lib/rattler/parsers/node_code.rb +47 -30
  145. data/lib/rattler/parsers/parser.rb +63 -32
  146. data/lib/rattler/parsers/parser_scope.rb +88 -0
  147. data/lib/rattler/parsers/predicate.rb +12 -10
  148. data/lib/rattler/parsers/repeat.rb +15 -8
  149. data/lib/rattler/parsers/rule.rb +8 -23
  150. data/lib/rattler/parsers/rule_set.rb +67 -12
  151. data/lib/rattler/parsers/semantic.rb +36 -0
  152. data/lib/rattler/parsers/semantic_action.rb +39 -0
  153. data/lib/rattler/parsers/sequence.rb +25 -40
  154. data/lib/rattler/parsers/sequencing.rb +40 -0
  155. data/lib/rattler/parsers/skip.rb +11 -12
  156. data/lib/rattler/parsers/super.rb +33 -0
  157. data/lib/rattler/parsers/token.rb +3 -13
  158. data/lib/rattler/rake_task.rb +50 -0
  159. data/lib/rattler/runner.rb +19 -22
  160. data/lib/rattler/runtime.rb +0 -10
  161. data/lib/rattler/runtime/extended_packrat_parser.rb +40 -45
  162. data/lib/rattler/runtime/packrat_parser.rb +17 -31
  163. data/lib/rattler/runtime/parse_failure.rb +16 -26
  164. data/lib/rattler/runtime/parse_node.rb +8 -18
  165. data/lib/rattler/runtime/parser.rb +6 -18
  166. data/lib/rattler/runtime/parser_helper.rb +3 -10
  167. data/lib/rattler/runtime/recursive_descent_parser.rb +26 -23
  168. data/lib/rattler/runtime/syntax_error.rb +0 -10
  169. data/lib/rattler/util.rb +2 -6
  170. data/lib/rattler/util/grammar_cli.rb +19 -0
  171. data/lib/rattler/util/graphviz.rb +6 -17
  172. data/lib/rattler/util/graphviz/digraph_builder.rb +10 -17
  173. data/lib/rattler/util/graphviz/node_builder.rb +45 -31
  174. data/lib/rattler/util/line_counter.rb +11 -20
  175. data/lib/rattler/util/node.rb +52 -30
  176. data/lib/rattler/util/parser_cli.rb +84 -0
  177. data/lib/rattler/util/parser_spec_helper.rb +8 -12
  178. data/spec/rattler/compiler/assert_compiler_examples.rb +284 -0
  179. data/spec/rattler/compiler/attributed_sequence_compiler_examples.rb +154 -0
  180. data/spec/rattler/compiler/disallow_compiler_examples.rb +293 -0
  181. data/spec/rattler/compiler/grammar_parser_spec.rb +700 -0
  182. data/spec/rattler/{back_end → compiler}/optimizer/flatten_choice_spec.rb +1 -1
  183. data/spec/rattler/{back_end → compiler}/optimizer/flatten_sequence_spec.rb +1 -1
  184. data/spec/rattler/compiler/optimizer/inline_regular_rules_spec.rb +50 -0
  185. data/spec/rattler/{back_end → compiler}/optimizer/join_match_capturing_sequence_spec.rb +106 -22
  186. data/spec/rattler/{back_end → compiler}/optimizer/join_match_choice_spec.rb +1 -1
  187. data/spec/rattler/{back_end → compiler}/optimizer/join_match_matching_sequence_spec.rb +1 -1
  188. data/spec/rattler/{back_end → compiler}/optimizer/join_predicate_bare_match_spec.rb +1 -1
  189. data/spec/rattler/{back_end → compiler}/optimizer/join_predicate_nested_match_spec.rb +1 -1
  190. data/spec/rattler/{back_end → compiler}/optimizer/join_predicate_or_bare_match_spec.rb +1 -1
  191. data/spec/rattler/{back_end → compiler}/optimizer/join_predicate_or_nested_match_spec.rb +1 -1
  192. data/spec/rattler/{back_end → compiler}/optimizer/reduce_repeat_match_spec.rb +1 -1
  193. data/spec/rattler/compiler/optimizer/remove_meaningless_wrapper_spec.rb +82 -0
  194. data/spec/rattler/{back_end → compiler}/optimizer/simplify_redundant_repeat_spec.rb +1 -1
  195. data/spec/rattler/{back_end → compiler}/optimizer/simplify_token_match_spec.rb +1 -1
  196. data/spec/rattler/{back_end → compiler}/optimizer_spec.rb +1 -1
  197. data/spec/rattler/{back_end → compiler}/parser_generator/apply_generator_spec.rb +1 -39
  198. data/spec/rattler/{back_end → compiler}/parser_generator/assert_generator_spec.rb +1 -55
  199. data/spec/rattler/compiler/parser_generator/attributed_sequence_generator_spec.rb +699 -0
  200. data/spec/rattler/{back_end → compiler}/parser_generator/back_reference_generator_spec.rb +3 -56
  201. data/spec/rattler/{back_end → compiler}/parser_generator/choice_generator_spec.rb +1 -63
  202. data/spec/rattler/{back_end → compiler}/parser_generator/disallow_generator_spec.rb +1 -55
  203. data/spec/rattler/{back_end → compiler}/parser_generator/e_symbol_generator_spec.rb +1 -39
  204. data/spec/rattler/{back_end → compiler}/parser_generator/eof_generator_spec.rb +1 -39
  205. data/spec/rattler/{back_end → compiler}/parser_generator/fail_generator_spec.rb +94 -23
  206. data/spec/rattler/compiler/parser_generator/grammar_generator_spec.rb +98 -0
  207. data/spec/rattler/compiler/parser_generator/group_match_generator_spec.rb +67 -0
  208. data/spec/rattler/{back_end → compiler}/parser_generator/group_match_spec.rb +1 -1
  209. data/spec/rattler/{back_end → compiler}/parser_generator/label_generator_spec.rb +1 -55
  210. data/spec/rattler/{back_end → compiler}/parser_generator/list0_generator_examples.rb +0 -88
  211. data/spec/rattler/{back_end → compiler}/parser_generator/list1_generator_examples.rb +0 -88
  212. data/spec/rattler/{back_end → compiler}/parser_generator/list_generator_spec.rb +1 -227
  213. data/spec/rattler/{back_end → compiler}/parser_generator/match_generator_spec.rb +1 -55
  214. data/spec/rattler/compiler/parser_generator/node_action_generator_spec.rb +135 -0
  215. data/spec/rattler/{back_end → compiler}/parser_generator/one_or_more_generator_examples.rb +0 -74
  216. data/spec/rattler/{back_end → compiler}/parser_generator/optional_generator_examples.rb +0 -62
  217. data/spec/rattler/{back_end → compiler}/parser_generator/repeat_generator_spec.rb +66 -1
  218. data/spec/rattler/{back_end → compiler}/parser_generator/rule_generator_spec.rb +3 -2
  219. data/spec/rattler/{back_end → compiler}/parser_generator/rule_set_generator_spec.rb +9 -27
  220. data/spec/rattler/compiler/parser_generator/semantic_action_generator_spec.rb +437 -0
  221. data/spec/rattler/{back_end → compiler}/parser_generator/sequence_generator_spec.rb +234 -68
  222. data/spec/rattler/{back_end → compiler}/parser_generator/skip_generator_spec.rb +1 -55
  223. data/spec/rattler/compiler/parser_generator/super_generator_spec.rb +93 -0
  224. data/spec/rattler/{back_end → compiler}/parser_generator/token_generator_spec.rb +1 -55
  225. data/spec/rattler/{back_end → compiler}/parser_generator/zero_or_more_generator_examples.rb +0 -74
  226. data/spec/rattler/{back_end → compiler}/ruby_generator_spec.rb +13 -13
  227. data/spec/rattler/compiler/semantic_action_compiler_examples.rb +57 -0
  228. data/spec/rattler/{back_end → compiler}/shared_compiler_examples.rb +111 -140
  229. data/spec/rattler/{back_end → compiler}/skip_compiler_examples.rb +60 -57
  230. data/spec/rattler/{back_end → compiler}/token_compiler_examples.rb +99 -104
  231. data/spec/rattler/compiler_spec.rb +67 -0
  232. data/spec/rattler/parsers/action_code_spec.rb +34 -18
  233. data/spec/rattler/{grammar → parsers}/analysis_spec.rb +13 -67
  234. data/spec/rattler/parsers/apply_spec.rb +6 -0
  235. data/spec/rattler/parsers/assert_spec.rb +38 -2
  236. data/spec/rattler/parsers/attributed_sequence_spec.rb +204 -0
  237. data/spec/rattler/parsers/back_reference_spec.rb +6 -0
  238. data/spec/rattler/parsers/choice_spec.rb +38 -1
  239. data/spec/rattler/parsers/combinator_parser_spec.rb +2 -1
  240. data/spec/rattler/parsers/disallow_spec.rb +38 -2
  241. data/spec/rattler/parsers/e_symbol_spec.rb +6 -0
  242. data/spec/rattler/parsers/eof_spec.rb +6 -0
  243. data/spec/rattler/parsers/fail_spec.rb +6 -0
  244. data/spec/rattler/{grammar → parsers}/grammar_spec.rb +10 -15
  245. data/spec/rattler/parsers/label_spec.rb +30 -0
  246. data/spec/rattler/parsers/list_parser_spec.rb +31 -2
  247. data/spec/rattler/parsers/match_spec.rb +6 -0
  248. data/spec/rattler/parsers/node_action_spec.rb +121 -0
  249. data/spec/rattler/parsers/parser_scope_spec.rb +105 -0
  250. data/spec/rattler/parsers/repeat_spec.rb +56 -0
  251. data/spec/rattler/parsers/rule_set_spec.rb +42 -0
  252. data/spec/rattler/parsers/semantic_action_spec.rb +89 -0
  253. data/spec/rattler/parsers/sequence_spec.rb +156 -12
  254. data/spec/rattler/parsers/skip_spec.rb +21 -0
  255. data/spec/rattler/parsers/super_spec.rb +45 -0
  256. data/spec/rattler/parsers/token_spec.rb +33 -14
  257. data/spec/rattler/runtime/extended_packrat_parser_spec.rb +10 -8
  258. data/spec/rattler/runtime/recursive_descent_parser_spec.rb +26 -0
  259. data/spec/rattler/runtime/shared_parser_examples.rb +22 -16
  260. data/spec/rattler/util/graphviz/node_builder_spec.rb +33 -17
  261. data/spec/rattler/util/line_counter_spec.rb +21 -21
  262. data/spec/rattler/util/node_spec.rb +62 -0
  263. data/spec/rattler_spec.rb +7 -41
  264. data/spec/spec_helper.rb +1 -2
  265. data/spec/support/combinator_parser_spec_helper.rb +1 -1
  266. data/spec/support/compiler_spec_helper.rb +0 -4
  267. data/spec/support/parser_generator_spec_helper.rb +7 -7
  268. data/spec/support/runtime_parser_spec_helper.rb +57 -3
  269. metadata +447 -303
  270. data/features/grammar/character_class.feature +0 -20
  271. data/features/grammar/nonterminal.feature +0 -24
  272. data/features/grammar/one_or_more.feature +0 -34
  273. data/features/grammar/ordered_choice.feature +0 -21
  274. data/features/grammar/posix_class.feature +0 -70
  275. data/features/grammar/sequence.feature +0 -20
  276. data/features/grammar/zero_or_more.feature +0 -34
  277. data/lib/rattler/back_end.rb +0 -22
  278. data/lib/rattler/back_end/compiler.rb +0 -128
  279. data/lib/rattler/back_end/optimizer.rb +0 -101
  280. data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +0 -46
  281. data/lib/rattler/back_end/optimizer/join_match_sequence.rb +0 -17
  282. data/lib/rattler/back_end/optimizer/join_predicate_match.rb +0 -17
  283. data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +0 -17
  284. data/lib/rattler/back_end/optimizer/optimization_context.rb +0 -72
  285. data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +0 -32
  286. data/lib/rattler/back_end/optimizer/specialize_repeat.rb +0 -40
  287. data/lib/rattler/back_end/parser_generator.rb +0 -113
  288. data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +0 -45
  289. data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +0 -45
  290. data/lib/rattler/back_end/parser_generator/group_match.rb +0 -26
  291. data/lib/rattler/back_end/parser_generator/label_generator.rb +0 -64
  292. data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +0 -24
  293. data/lib/rattler/back_end/parser_generator/rule_generator.rb +0 -53
  294. data/lib/rattler/back_end/parser_generator/sequence_generator.rb +0 -190
  295. data/lib/rattler/back_end/parser_generator/skip_propogating.rb +0 -16
  296. data/lib/rattler/back_end/parser_generator/token_propogating.rb +0 -10
  297. data/lib/rattler/grammar.rb +0 -43
  298. data/lib/rattler/grammar/grammar_dsl.rb +0 -51
  299. data/lib/rattler/grammar/metagrammar.rb +0 -990
  300. data/lib/rattler/grammar/rattler.rtlr +0 -183
  301. data/lib/rattler/parsers/assert_code.rb +0 -31
  302. data/lib/rattler/parsers/direct_action.rb +0 -85
  303. data/lib/rattler/parsers/disallow_code.rb +0 -31
  304. data/lib/rattler/parsers/dispatch_action.rb +0 -121
  305. data/lib/rattler/parsers/effect_code.rb +0 -31
  306. data/lib/rattler/parsers/parser_dsl.rb +0 -414
  307. data/lib/rattler/parsers/semantic_assert.rb +0 -19
  308. data/lib/rattler/parsers/semantic_disallow.rb +0 -19
  309. data/lib/rattler/parsers/side_effect.rb +0 -19
  310. data/spec/rattler/back_end/assert_compiler_examples.rb +0 -187
  311. data/spec/rattler/back_end/compiler_spec.rb +0 -43
  312. data/spec/rattler/back_end/direct_action_compiler_examples.rb +0 -227
  313. data/spec/rattler/back_end/disallow_compiler_examples.rb +0 -187
  314. data/spec/rattler/back_end/dispatch_action_compiler_examples.rb +0 -225
  315. data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +0 -80
  316. data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +0 -204
  317. data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +0 -204
  318. data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +0 -185
  319. data/spec/rattler/back_end/semantic_assert_compiler_examples.rb +0 -152
  320. data/spec/rattler/back_end/semantic_disallow_compiler_examples.rb +0 -152
  321. data/spec/rattler/back_end/side_effect_compiler_examples.rb +0 -227
  322. data/spec/rattler/grammar/grammar_parser_spec.rb +0 -626
  323. data/spec/rattler/parsers/direct_action_spec.rb +0 -224
  324. data/spec/rattler/parsers/dispatch_action_spec.rb +0 -209
  325. data/spec/rattler/parsers/node_code_spec.rb +0 -59
  326. data/spec/rattler/parsers/parser_dsl_spec.rb +0 -334
  327. data/spec/rattler/parsers/semantic_assert_spec.rb +0 -83
  328. data/spec/rattler/parsers/semantic_disallow_spec.rb +0 -83
  329. data/spec/rattler/parsers/side_effect_spec.rb +0 -214
@@ -0,0 +1,84 @@
1
+ require 'rattler/util'
2
+ require 'optparse'
3
+
4
+ module Rattler::Util
5
+
6
+ # +ParserCLI+ defines a command line interface for generated parsers.
7
+ class ParserCLI
8
+
9
+ # The supported graph file formats
10
+ @@graph_formats = %w{jpg png svg pdf ps ps2 eps}
11
+
12
+ # Create and run the command line interface for the given parser class
13
+ #
14
+ # @param (see #initialize)
15
+ def self.run(parser_class)
16
+ self.new(parser_class).run
17
+ end
18
+
19
+ # Create a new command line interface for the given parser class
20
+ #
21
+ # @param [Class] parser_class the parser class to run the command line
22
+ # interface for
23
+ def initialize(parser_class)
24
+ @parser_class = parser_class
25
+
26
+ OptionParser.new do |opts|
27
+
28
+ opts.banner = "Usage: #{File.basename($0)} [filenames] [options]"
29
+
30
+ opts.separator ''
31
+
32
+ opts.on '-g', '--graphviz',
33
+ 'Display the parse tree using GraphViz dotty' do |g|
34
+ @graphviz = {:dot => '|dotty'}
35
+ end
36
+
37
+ @@graph_formats.each do |format|
38
+ a = 'aefhilmnorsx'.include?(format[0]) ? 'an' : 'a'
39
+ desc = "#{format.upcase} file"
40
+ opts.on "--#{format} FILENAME",
41
+ "Output the parse tree as #{a} #{desc} using GraphViz" do |f|
42
+ @graphviz = {format => f}
43
+ end
44
+ end
45
+
46
+ opts.on '-f', '--file FILENAME',
47
+ 'Output the parse tree as a GraphViz DOT language file' do |file|
48
+ @graphviz = {:dot => file}
49
+ end
50
+
51
+ opts.on '-d', '--dot',
52
+ 'Output the parse tree in the GraphViz DOT language' do |d|
53
+ @graphviz = {:dot => nil}
54
+ end
55
+
56
+ opts.separator ''
57
+
58
+ opts.on_tail '-h', '--help', 'Show this message' do
59
+ abort "#{opts}\n"
60
+ end
61
+ end.parse!(ARGV)
62
+ end
63
+
64
+ # Run the command line interface
65
+ def run
66
+ show_result @parser_class.parse!(ARGF.read)
67
+ rescue Rattler::Runtime::SyntaxError => e
68
+ puts e
69
+ end
70
+
71
+ private
72
+
73
+ # @private
74
+ def show_result(result) #:nodoc:
75
+ if @graphviz
76
+ GraphViz.digraph(result).output(@graphviz)
77
+ else
78
+ require 'pp'
79
+ pp result
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -1,34 +1,28 @@
1
- #
2
- # = rattler/util/parser_spec_helper.rb
3
- #
4
- # Author:: Jason Arhart
5
- # Documentation:: Author
6
- #
7
1
  require 'rattler/util'
8
2
 
9
3
  module Rattler::Util
10
- #
4
+
11
5
  # +ParserSpecHelper+ defines a fluent interface for writing RSpec examples
12
6
  # for parsers.
13
7
  #
14
8
  # @example
15
9
  #
16
- # require 'rattler/grammar/grammar_parser'
10
+ # require 'my_awesome_language/my_awesome_parser'
17
11
  # require 'rattler/util/parser_spec_helper'
18
12
  #
19
- # describe Rattler::Grammar::GrammarParser do
13
+ # describe MyAwesomeLanguage::MyAwesomeParser do
20
14
  # include Rattler::Util::ParserSpecHelper
21
15
  #
22
16
  # describe '#match(:var_name)' do
23
17
  # it 'recognizes variable names' do
24
18
  # matching(' fooBar ').as(:var_name).should result_in('fooBar').at(7)
25
- # matching(' FooBar ').as(:var_name).should fail.with_message('variable name expected')
19
+ # end
20
+ # it 'rejects non-variables' do
21
+ # matching(' 42 ').as(:var_name).should fail.with_message('variable name expected')
26
22
  # end
27
23
  # end
28
24
  # end
29
25
  #
30
- # @author Jason Arhart
31
- #
32
26
  module ParserSpecHelper
33
27
 
34
28
  # Return a parse result to be matched using #result_in or #fail
@@ -49,6 +43,8 @@ module Rattler::Util
49
43
  Matching.new(parser(source))
50
44
  end
51
45
 
46
+ private
47
+
52
48
  def parser(source)
53
49
  (self.respond_to?(:parser_class) ? parser_class : described_class).new(source)
54
50
  end
@@ -0,0 +1,284 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ shared_examples_for 'a compiled parser with an assert' do
4
+ include CompilerSpecHelper
5
+ include RuntimeParserSpecHelper
6
+
7
+ subject { compiled_parser }
8
+
9
+ let(:reference_parser) { combinator_parser grammar }
10
+
11
+ let(:grammar) { Rattler::Parsers::Grammar[Rattler::Parsers::RuleSet[*rules]] }
12
+
13
+ context 'with a nested match rule' do
14
+ let(:rules) { [
15
+ rule(:word) { assert(/\w+/) }
16
+ ] }
17
+ it { should parse('abc123 ').succeeding.like reference_parser }
18
+ it { should parse(' ').failing.like reference_parser }
19
+ end
20
+
21
+ context 'with a nested eof rule' do
22
+ let(:rules) { [
23
+ rule(:foo) { assert(eof) }
24
+ ] }
25
+ it { should parse('').succeeding.like reference_parser }
26
+ it { should parse('foo').from(3).succeeding.like reference_parser }
27
+ it { should parse('foo').failing.like reference_parser }
28
+ end
29
+
30
+ context 'with a nested "E" symbol rule' do
31
+ let(:rules) { [
32
+ rule(:foo) { assert(e) }
33
+ ] }
34
+ it { should parse('').succeeding.like reference_parser }
35
+ it { should parse('foo').succeeding.like reference_parser }
36
+ end
37
+
38
+ context 'with a nested choice rule' do
39
+ let(:rules) { [
40
+ rule(:word) { assert(match(/[[:alpha:]]+/) | match(/[[:digit:]]+/)) }
41
+ ] }
42
+ it { should parse('abc123 ').succeeding.like reference_parser }
43
+ it { should parse(' ').failing.like reference_parser }
44
+ end
45
+
46
+ context 'with a nested sequence rule' do
47
+ let(:rules) { [
48
+ rule(:word) { assert(match(/[[:alpha:]]+/) & match(/[[:digit:]]+/)) }
49
+ ] }
50
+ it { should parse('abc123 ').succeeding.like reference_parser }
51
+ it { should parse(' ').failing.like reference_parser }
52
+
53
+ context 'with a semantic action' do
54
+
55
+ context 'when the expression has parameters' do
56
+ let(:rules) { [
57
+ rule(:a) { assert(match(/\d+/) >> semantic_action('|a| a.to_i * 2')) }
58
+ ] }
59
+ it { should parse('451a').succeeding.like reference_parser }
60
+ it { should parse(' ').failing.like reference_parser }
61
+ end
62
+
63
+ context 'when the expression uses "_"' do
64
+
65
+ context 'given a single capture' do
66
+ let(:rules) { [
67
+ rule(:a) { assert(match(/\d+/) >> semantic_action('_ * 2')) }
68
+ ] }
69
+ it { should parse('451a').succeeding.like reference_parser }
70
+ it { should parse(' ').failing.like reference_parser }
71
+ end
72
+
73
+ context 'given multiple captures' do
74
+ let(:rules) { [
75
+ rule(:a) { assert(
76
+ (match(/\d+/) & skip(/\s+/) & match(/\d+/)) >> semantic_action('_')
77
+ ) }
78
+ ] }
79
+ it { should parse('23 42').succeeding.like reference_parser }
80
+ it { should parse(' ').failing.like reference_parser }
81
+ end
82
+ end
83
+
84
+ context 'when the expression uses labels' do
85
+ let(:rules) { [
86
+ rule(:a) { assert(label(:a, /\d+/) >> semantic_action('a.to_i * 2')) }
87
+ ] }
88
+ it { should parse('451a').succeeding.like reference_parser }
89
+ it { should parse(' ').failing.like reference_parser }
90
+ end
91
+ end
92
+ end
93
+
94
+ context 'with a nested optional rule' do
95
+ let(:rules) { [
96
+ rule(:word) { assert(match(/\w+/).optional) }
97
+ ] }
98
+ it { should parse('abc123 ').succeeding.like reference_parser }
99
+ it { should parse(' ').succeeding.like reference_parser }
100
+ end
101
+
102
+ context 'with a nested zero-or-more rule' do
103
+ let(:rules) { [
104
+ rule(:word) { assert(match(/\w/).zero_or_more) }
105
+ ] }
106
+ it { should parse('abc123 ').succeeding.like reference_parser }
107
+ it { should parse(' ').succeeding.like reference_parser }
108
+ end
109
+
110
+ context 'with a nested one-or-more rule' do
111
+ let(:rules) { [
112
+ rule(:word) { assert(match(/\w/).one_or_more) }
113
+ ] }
114
+ it { should parse('abc123 ').succeeding.like reference_parser }
115
+ it { should parse(' ').failing.like reference_parser }
116
+ end
117
+
118
+ context 'with a nested repeat rule' do
119
+ let(:rules) { [
120
+ rule(:word) { assert(match(/\w/).repeat(2, nil)) }
121
+ ] }
122
+ it { should parse('abc123 ').succeeding.like reference_parser }
123
+ it { should parse('a ').failing.like reference_parser }
124
+
125
+ context 'with zero-or-more bounds' do
126
+ let(:rules) { [
127
+ rule(:word) { assert(match(/\w/).repeat(0, nil)) }
128
+ ] }
129
+ it { should parse('abc123 ').succeeding.like reference_parser }
130
+ it { should parse(' ').succeeding.like reference_parser }
131
+
132
+ context 'with an upper bound' do
133
+ let(:rules) { [
134
+ rule(:word) { assert(match(/\w/).repeat(0, 2)) }
135
+ ] }
136
+ it { should parse('abc123 ').succeeding.like reference_parser }
137
+ it { should parse(' ').succeeding.like reference_parser }
138
+ end
139
+ end
140
+
141
+ context 'with one-or-more bounds' do
142
+ let(:rules) { [
143
+ rule(:word) { assert(match(/\w/).repeat(1, nil)) }
144
+ ] }
145
+ it { should parse('abc123 ').succeeding.like reference_parser }
146
+ it { should parse(' ').failing.like reference_parser }
147
+
148
+ context 'with an upper bound' do
149
+ let(:rules) { [
150
+ rule(:word) { assert(match(/\w/).repeat(1, 2)) }
151
+ ] }
152
+ it { should parse('abc123 ').succeeding.like reference_parser }
153
+ it { should parse(' ').failing.like reference_parser }
154
+ end
155
+ end
156
+ end
157
+
158
+ context 'with a nested list rule' do
159
+ let(:rules) { [
160
+ rule(:foo) { assert(match(/\w+/).list(match(/[,;]/), 2, nil)) }
161
+ ] }
162
+ it { should parse('foo ').failing.like reference_parser }
163
+ it { should parse('foo,bar;baz ').succeeding.like reference_parser }
164
+
165
+ context 'with an upper bound' do
166
+ let(:rules) { [
167
+ rule(:foo) { assert(match(/\w+/).list(match(/[,;]/), 2, 4)) }
168
+ ] }
169
+ it { should parse('foo ').failing.like reference_parser }
170
+ it { should parse('foo,bar;baz ').succeeding.like reference_parser }
171
+ end
172
+
173
+ context 'with a non-capturing parser' do
174
+ let(:rules) { [
175
+ rule(:foo) { assert(skip(/\w+/).list(match(/[,;]/), 2, nil)) }
176
+ ] }
177
+ it { should parse('foo ').failing.like reference_parser }
178
+ it { should parse('foo,bar;baz ').succeeding.like reference_parser }
179
+
180
+ context 'with an upper bound' do
181
+ let(:rules) { [
182
+ rule(:foo) { assert skip(/\w+/).list(match(/[,;]/), 2, 4) }
183
+ ] }
184
+ it { should parse('foo ').failing.like reference_parser }
185
+ it { should parse('foo,bar;baz ').succeeding.like reference_parser }
186
+ end
187
+ end
188
+ end
189
+
190
+ context 'with a nested apply rule' do
191
+ let(:rules) { [
192
+ rule(:foo) { match(:word) },
193
+ rule(:word) { assert(/\w+/) }
194
+ ] }
195
+ it { should parse('abc123 ').succeeding.like reference_parser }
196
+ it { should parse(' ').failing.like reference_parser }
197
+ end
198
+
199
+ context 'with a nested semantic action' do
200
+ let(:rules) { [
201
+ rule(:a) { assert(semantic_action('42')) }
202
+ ] }
203
+ it { should parse('anything').succeeding.like reference_parser }
204
+ end
205
+
206
+ context 'with a nested attributed sequence' do
207
+
208
+ context 'with a single capture and a semantic action' do
209
+
210
+ context 'when the action uses a parameter' do
211
+ let(:rules) { [
212
+ rule(:a) { assert(match(/\d+/) >> semantic_action('|a| a.to_i')) }
213
+ ] }
214
+ it { should parse('451a').succeeding.like reference_parser }
215
+ it { should parse(' ').failing.like reference_parser }
216
+ end
217
+
218
+ context 'when the action uses "_"' do
219
+ let(:rules) { [
220
+ rule(:a) { assert(match(/\d+/) >> semantic_action('_.to_i')) }
221
+ ] }
222
+ it { should parse('451a').succeeding.like reference_parser }
223
+ it { should parse(' ').failing.like reference_parser }
224
+ end
225
+ end
226
+
227
+ context 'with multiple captures and a semantic action' do
228
+
229
+ context 'when the action uses parameters' do
230
+ let(:rules) { [
231
+ rule(:a) { assert(
232
+ (match(/[a-z]+/) & match(/\d+/)) >> semantic_action('|a,b| b+a')
233
+ ) }
234
+ ] }
235
+ it { should parse('abc123').succeeding.like reference_parser }
236
+ it { should parse(' ').failing.like reference_parser }
237
+ end
238
+
239
+ context 'when the action uses "_"' do
240
+ let(:rules) { [
241
+ rule(:a) { assert(
242
+ (match(/[a-z]+/) & match(/\d+/)) >> semantic_action('_.reverse')
243
+ ) }
244
+ ] }
245
+ it { should parse('abc123').succeeding.like reference_parser }
246
+ it { should parse(' ').failing.like reference_parser }
247
+ end
248
+ end
249
+
250
+ context 'with a single labeled capture and a semantic action' do
251
+ let(:rules) { [
252
+ rule(:e) { assert(label(:a, /\d+/) >> semantic_action('a.to_i')) }
253
+ ] }
254
+ it { should parse('451a').succeeding.like reference_parser }
255
+ it { should parse(' ').failing.like reference_parser }
256
+ end
257
+
258
+ context 'with multiple labeled captures and a semantic action' do
259
+ let(:rules) { [
260
+ rule(:e) { assert(
261
+ (label(:a, /[a-z]+/) & label(:b, /\d+/)) >> semantic_action('b + a')
262
+ ) }
263
+ ] }
264
+ it { should parse('abc123').succeeding.like reference_parser }
265
+ it { should parse(' ').failing.like reference_parser }
266
+ end
267
+ end
268
+
269
+ context 'with a nested token rule' do
270
+ let(:rules) { [
271
+ rule(:word) { assert(token(/\w+/)) }
272
+ ] }
273
+ it { should parse('abc123 ').succeeding.like reference_parser }
274
+ it { should parse(' ').failing.like reference_parser }
275
+ end
276
+
277
+ context 'with a nested skip rule' do
278
+ let(:rules) { [
279
+ rule(:word) { assert(skip(/\w+/)) }
280
+ ] }
281
+ it { should parse('abc123 ').succeeding.like reference_parser }
282
+ it { should parse(' ').failing.like reference_parser }
283
+ end
284
+ end
@@ -0,0 +1,154 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ shared_examples_for 'a compiled parser with an attributed sequence' do
4
+ include CompilerSpecHelper
5
+ include RuntimeParserSpecHelper
6
+
7
+ subject { compiled_parser }
8
+
9
+ let(:reference_parser) { combinator_parser grammar }
10
+
11
+ let(:grammar) { Rattler::Parsers::Grammar[Rattler::Parsers::RuleSet[*rules]] }
12
+
13
+ context 'with a single capture and a semantic action' do
14
+
15
+ context 'when the action uses no parameters' do
16
+ let(:rules) { [
17
+ rule(:a) { match(/\d+/) >> semantic_action('42') }
18
+ ] }
19
+ it { should parse('451a').succeeding.like reference_parser }
20
+ it { should parse(' ').failing.like reference_parser }
21
+ end
22
+
23
+ context 'when the action uses a parameter' do
24
+ let(:rules) { [
25
+ rule(:a) { match(/\d+/) >> semantic_action('|a| a.to_i') }
26
+ ] }
27
+ it { should parse('451a').succeeding.like reference_parser }
28
+ it { should parse(' ').failing.like reference_parser }
29
+ end
30
+
31
+ context 'when the action uses "_"' do
32
+ let(:rules) { [
33
+ rule(:a) { match(/\d+/) >> semantic_action('_.to_i') }
34
+ ] }
35
+ it { should parse('451a').succeeding.like reference_parser }
36
+ it { should parse(' ').failing.like reference_parser }
37
+ end
38
+ end
39
+
40
+ context 'with a single capture and a node action' do
41
+ let(:rules) { [
42
+ rule(:a) { match(/\d+/) >> node_action('Rattler::Runtime::ParseNode') }
43
+ ] }
44
+ it { should parse('451a').succeeding.like reference_parser }
45
+ it { should parse(' ').failing.like reference_parser }
46
+
47
+ context 'when the action has node attributes' do
48
+ let(:rules) { [
49
+ rule(:a) do
50
+ match(/\d+/) >> node_action('Rattler::Runtime::ParseNode', :node_attrs => {:name => "FOO"})
51
+ end
52
+ ] }
53
+ it { should parse('451a').succeeding.like reference_parser }
54
+ it { should parse(' ').failing.like reference_parser }
55
+ end
56
+ end
57
+
58
+ context 'with a capturing nonterminal and a node action' do
59
+ let(:rules) { [
60
+ rule(:a) { match(:b) >> node_action('Rattler::Runtime::ParseNode') },
61
+ rule(:b) { match(/\d+/) }
62
+ ] }
63
+ it { should parse('451a').succeeding.like reference_parser }
64
+ it { should parse(' ').failing.like reference_parser }
65
+ end
66
+
67
+ context 'with a non-capturing nonterminal and a node action' do
68
+ let(:rules) { [
69
+ rule(:a) { match(:b) >> node_action('Rattler::Runtime::ParseNode') },
70
+ rule(:b) { skip(/\d+/) }
71
+ ] }
72
+ it { should parse('451a').succeeding.like reference_parser }
73
+ it { should parse(' ').failing.like reference_parser }
74
+ end
75
+
76
+ context 'with multiple captures and a semantic action' do
77
+
78
+ context 'when the action uses parameters' do
79
+ let(:rules) { [
80
+ rule(:a) {
81
+ (match(/[a-z]+/) & match(/\d+/)) >> semantic_action('|a,b| b+a')
82
+ }
83
+ ] }
84
+ it { should parse('abc123').succeeding.like reference_parser }
85
+ it { should parse(' ').failing.like reference_parser }
86
+ end
87
+
88
+ context 'when the action uses "_"' do
89
+ let(:rules) { [
90
+ rule(:a) {
91
+ (match(/[a-z]+/) & match(/\d+/)) >> semantic_action('_.reverse')
92
+ }
93
+ ] }
94
+ it { should parse('abc123').succeeding.like reference_parser }
95
+ it { should parse(' ').failing.like reference_parser }
96
+ end
97
+ end
98
+
99
+ context 'with multiple captures and a node action' do
100
+ let(:rules) { [
101
+ rule(:a) {
102
+ (match(/[a-z]+/) & match(/\d+/)) >> node_action('Rattler::Runtime::ParseNode')
103
+ }
104
+ ] }
105
+ it { should parse('abc123').succeeding.like reference_parser }
106
+ it { should parse(' ').failing.like reference_parser }
107
+ end
108
+
109
+ context 'with a single labeled capture and a semantic action' do
110
+ let(:rules) { [
111
+ rule(:e) { label(:a, /\d+/) >> semantic_action('a.to_i') }
112
+ ] }
113
+ it { should parse('451a').succeeding.like reference_parser }
114
+ it { should parse(' ').failing.like reference_parser }
115
+ end
116
+
117
+ context 'with multiple labeled captures and a semantic action' do
118
+ let(:rules) { [
119
+ rule(:e) {
120
+ (label(:a, /[a-z]+/) & label(:b, /\d+/)) >> semantic_action('b + a')
121
+ }
122
+ ] }
123
+ it { should parse('abc123').succeeding.like reference_parser }
124
+ it { should parse(' ').failing.like reference_parser }
125
+ end
126
+
127
+ context 'with a single labeled capture and a node action' do
128
+ let(:rules) { [
129
+ rule(:e) { label(:a, /\d+/) >> node_action('Rattler::Runtime::ParseNode') }
130
+ ] }
131
+ it { should parse('451a').succeeding.like reference_parser }
132
+ it { should parse(' ').failing.like reference_parser }
133
+
134
+ context 'when the action has node attributes' do
135
+ let(:rules) { [
136
+ rule(:e) {
137
+ label(:a, /\d+/) >> node_action('Rattler::Runtime::ParseNode', :node_attrs => {:name => "FOO"})
138
+ }
139
+ ] }
140
+ it { should parse('451a').succeeding.like reference_parser }
141
+ it { should parse(' ').failing.like reference_parser }
142
+ end
143
+ end
144
+
145
+ context 'with multiple labeled captures and a node action' do
146
+ let(:rules) { [
147
+ rule(:e) {
148
+ (label(:a, /[a-z]+/) & label(:b, /\d+/)) >> node_action('Rattler::Runtime::ParseNode')
149
+ }
150
+ ] }
151
+ it { should parse('abc123').succeeding.like reference_parser }
152
+ it { should parse(' ').failing.like reference_parser }
153
+ end
154
+ end