rattler 0.3.0 → 0.4.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 (182) hide show
  1. data/README.rdoc +57 -37
  2. data/features/command_line/dest_option.feature +8 -21
  3. data/features/command_line/lib_option.feature +37 -0
  4. data/features/command_line/parser_generator.feature +7 -4
  5. data/features/grammar/back_reference.feature +37 -0
  6. data/features/grammar/fail.feature +3 -3
  7. data/features/grammar/labels.feature +11 -3
  8. data/features/grammar/list_matching.feature +14 -5
  9. data/features/grammar/literal.feature +30 -4
  10. data/features/grammar/nonterminal.feature +1 -1
  11. data/features/grammar/ordered_choice.feature +2 -2
  12. data/features/grammar/skip_operator.feature +1 -1
  13. data/features/grammar/symantic_action.feature +7 -7
  14. data/features/grammar/whitespace.feature +2 -2
  15. data/features/step_definitions/grammar_steps.rb +2 -2
  16. data/lib/rattler/back_end.rb +1 -0
  17. data/lib/rattler/back_end/compiler.rb +19 -20
  18. data/lib/rattler/back_end/optimizer.rb +100 -0
  19. data/lib/rattler/back_end/optimizer/composite_reducing.rb +18 -0
  20. data/lib/rattler/back_end/optimizer/flatten_choice.rb +31 -0
  21. data/lib/rattler/back_end/optimizer/flatten_sequence.rb +59 -0
  22. data/lib/rattler/back_end/optimizer/flattening.rb +17 -0
  23. data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +46 -0
  24. data/lib/rattler/back_end/optimizer/join_match_capturing_sequence.rb +71 -0
  25. data/lib/rattler/back_end/optimizer/join_match_choice.rb +37 -0
  26. data/lib/rattler/back_end/optimizer/join_match_matching_sequence.rb +38 -0
  27. data/lib/rattler/back_end/optimizer/join_match_sequence.rb +17 -0
  28. data/lib/rattler/back_end/optimizer/join_predicate_bare_match.rb +68 -0
  29. data/lib/rattler/back_end/optimizer/join_predicate_match.rb +17 -0
  30. data/lib/rattler/back_end/optimizer/join_predicate_nested_match.rb +37 -0
  31. data/lib/rattler/back_end/optimizer/join_predicate_or_bare_match.rb +68 -0
  32. data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +17 -0
  33. data/lib/rattler/back_end/optimizer/join_predicate_or_nested_match.rb +36 -0
  34. data/lib/rattler/back_end/optimizer/match_joining.rb +60 -0
  35. data/lib/rattler/back_end/optimizer/optimization.rb +94 -0
  36. data/lib/rattler/back_end/optimizer/optimization_context.rb +72 -0
  37. data/lib/rattler/back_end/optimizer/optimization_sequence.rb +37 -0
  38. data/lib/rattler/back_end/optimizer/optimize_children.rb +46 -0
  39. data/lib/rattler/back_end/optimizer/reduce_repeat_match.rb +44 -0
  40. data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +32 -0
  41. data/lib/rattler/back_end/optimizer/simplify_redundant_repeat.rb +43 -0
  42. data/lib/rattler/back_end/optimizer/simplify_token_match.rb +38 -0
  43. data/lib/rattler/back_end/parser_generator.rb +21 -14
  44. data/lib/rattler/back_end/parser_generator/apply_generator.rb +35 -35
  45. data/lib/rattler/back_end/parser_generator/assert_generator.rb +29 -30
  46. data/lib/rattler/back_end/parser_generator/back_reference_generator.rb +93 -0
  47. data/lib/rattler/back_end/parser_generator/choice_generator.rb +33 -49
  48. data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +14 -14
  49. data/lib/rattler/back_end/parser_generator/disallow_generator.rb +29 -30
  50. data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +11 -13
  51. data/lib/rattler/back_end/parser_generator/expr_generator.rb +36 -56
  52. data/lib/rattler/back_end/parser_generator/fail_generator.rb +18 -18
  53. data/lib/rattler/back_end/parser_generator/group_match.rb +18 -0
  54. data/lib/rattler/back_end/parser_generator/group_match_generator.rb +76 -0
  55. data/lib/rattler/back_end/parser_generator/label_generator.rb +25 -6
  56. data/lib/rattler/back_end/parser_generator/list1_generator.rb +7 -7
  57. data/lib/rattler/back_end/parser_generator/list_generating.rb +19 -20
  58. data/lib/rattler/back_end/parser_generator/list_generator.rb +5 -5
  59. data/lib/rattler/back_end/parser_generator/match_generator.rb +52 -52
  60. data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +6 -6
  61. data/lib/rattler/back_end/parser_generator/optional_generator.rb +30 -29
  62. data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +8 -8
  63. data/lib/rattler/back_end/parser_generator/repeat_generating.rb +23 -25
  64. data/lib/rattler/back_end/parser_generator/rule_generator.rb +27 -79
  65. data/lib/rattler/back_end/parser_generator/rule_set_generator.rb +102 -0
  66. data/lib/rattler/back_end/parser_generator/sequence_generator.rb +49 -41
  67. data/lib/rattler/back_end/parser_generator/skip_generator.rb +14 -20
  68. data/lib/rattler/back_end/parser_generator/skip_propogating.rb +4 -4
  69. data/lib/rattler/back_end/parser_generator/sub_generating.rb +6 -0
  70. data/lib/rattler/back_end/parser_generator/token_generator.rb +12 -12
  71. data/lib/rattler/back_end/parser_generator/token_propogating.rb +2 -2
  72. data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +4 -4
  73. data/lib/rattler/grammar.rb +4 -3
  74. data/lib/rattler/grammar/analysis.rb +91 -0
  75. data/lib/rattler/grammar/grammar.rb +37 -25
  76. data/lib/rattler/grammar/grammar_parser.rb +19 -11
  77. data/lib/rattler/grammar/metagrammar.rb +569 -800
  78. data/lib/rattler/grammar/rattler.rtlr +162 -144
  79. data/lib/rattler/parsers.rb +5 -1
  80. data/lib/rattler/parsers/action_code.rb +29 -15
  81. data/lib/rattler/parsers/apply.rb +5 -5
  82. data/lib/rattler/parsers/assert.rb +4 -18
  83. data/lib/rattler/parsers/back_reference.rb +46 -0
  84. data/lib/rattler/parsers/choice.rb +6 -39
  85. data/lib/rattler/parsers/combinator_parser.rb +32 -0
  86. data/lib/rattler/parsers/combining.rb +3 -29
  87. data/lib/rattler/parsers/direct_action.rb +27 -30
  88. data/lib/rattler/parsers/disallow.rb +4 -18
  89. data/lib/rattler/parsers/dispatch_action.rb +30 -25
  90. data/lib/rattler/parsers/label.rb +9 -18
  91. data/lib/rattler/parsers/list.rb +3 -34
  92. data/lib/rattler/parsers/list1.rb +4 -36
  93. data/lib/rattler/parsers/list_parser.rb +64 -0
  94. data/lib/rattler/parsers/match.rb +7 -42
  95. data/lib/rattler/parsers/node_code.rb +44 -0
  96. data/lib/rattler/parsers/one_or_more.rb +7 -27
  97. data/lib/rattler/parsers/optional.rb +5 -25
  98. data/lib/rattler/parsers/parser.rb +16 -44
  99. data/lib/rattler/parsers/parser_dsl.rb +13 -3
  100. data/lib/rattler/parsers/predicate.rb +4 -12
  101. data/lib/rattler/parsers/rule.rb +18 -19
  102. data/lib/rattler/parsers/rule_set.rb +63 -0
  103. data/lib/rattler/parsers/sequence.rb +12 -46
  104. data/lib/rattler/parsers/skip.rb +12 -26
  105. data/lib/rattler/parsers/token.rb +6 -21
  106. data/lib/rattler/parsers/zero_or_more.rb +6 -26
  107. data/lib/rattler/runner.rb +66 -28
  108. data/lib/rattler/runtime/extended_packrat_parser.rb +26 -20
  109. data/lib/rattler/runtime/packrat_parser.rb +17 -21
  110. data/lib/rattler/runtime/parser.rb +12 -2
  111. data/lib/rattler/runtime/recursive_descent_parser.rb +3 -11
  112. data/lib/rattler/util.rb +2 -1
  113. data/lib/rattler/util/graphviz.rb +29 -0
  114. data/lib/rattler/util/graphviz/digraph_builder.rb +71 -0
  115. data/lib/rattler/util/graphviz/node_builder.rb +84 -0
  116. data/lib/rattler/util/node.rb +37 -19
  117. data/lib/rattler/util/parser_spec_helper.rb +61 -35
  118. data/spec/rattler/back_end/compiler_spec.rb +6 -860
  119. data/spec/rattler/back_end/optimizer/flatten_choice_spec.rb +70 -0
  120. data/spec/rattler/back_end/optimizer/flatten_sequence_spec.rb +130 -0
  121. data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +80 -0
  122. data/spec/rattler/back_end/optimizer/join_match_capturing_sequence_spec.rb +241 -0
  123. data/spec/rattler/back_end/optimizer/join_match_choice_spec.rb +100 -0
  124. data/spec/rattler/back_end/optimizer/join_match_matching_sequence_spec.rb +112 -0
  125. data/spec/rattler/back_end/optimizer/join_predicate_bare_match_spec.rb +194 -0
  126. data/spec/rattler/back_end/optimizer/join_predicate_nested_match_spec.rb +180 -0
  127. data/spec/rattler/back_end/optimizer/join_predicate_or_bare_match_spec.rb +153 -0
  128. data/spec/rattler/back_end/optimizer/join_predicate_or_nested_match_spec.rb +153 -0
  129. data/spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb +98 -0
  130. data/spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb +226 -0
  131. data/spec/rattler/back_end/optimizer/simplify_token_match_spec.rb +85 -0
  132. data/spec/rattler/back_end/parser_generator/apply_generator_spec.rb +38 -33
  133. data/spec/rattler/back_end/parser_generator/assert_generator_spec.rb +38 -33
  134. data/spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb +181 -0
  135. data/spec/rattler/back_end/parser_generator/choice_generator_spec.rb +38 -33
  136. data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +38 -33
  137. data/spec/rattler/back_end/parser_generator/disallow_generator_spec.rb +38 -33
  138. data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +38 -33
  139. data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +185 -0
  140. data/spec/rattler/back_end/parser_generator/label_generator_spec.rb +38 -33
  141. data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +10 -5
  142. data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +10 -5
  143. data/spec/rattler/back_end/parser_generator/match_generator_spec.rb +38 -33
  144. data/spec/rattler/back_end/parser_generator/one_or_more_generator_spec.rb +38 -33
  145. data/spec/rattler/back_end/parser_generator/optional_generator_spec.rb +38 -33
  146. data/spec/rattler/back_end/parser_generator/rule_generator_spec.rb +13 -46
  147. data/spec/rattler/back_end/parser_generator/rule_set_generator_spec.rb +97 -0
  148. data/spec/rattler/back_end/parser_generator/sequence_generator_spec.rb +38 -33
  149. data/spec/rattler/back_end/parser_generator/skip_generator_spec.rb +38 -33
  150. data/spec/rattler/back_end/parser_generator/token_generator_spec.rb +38 -33
  151. data/spec/rattler/back_end/parser_generator/zero_or_more_generator_spec.rb +39 -34
  152. data/spec/rattler/back_end/shared_compiler_examples.rb +885 -0
  153. data/spec/rattler/grammar/analysis_spec.rb +167 -0
  154. data/spec/rattler/grammar/grammar_parser_spec.rb +169 -179
  155. data/spec/rattler/grammar/grammar_spec.rb +24 -21
  156. data/spec/rattler/parsers/action_code_spec.rb +64 -19
  157. data/spec/rattler/parsers/apply_spec.rb +9 -9
  158. data/spec/rattler/parsers/back_reference_spec.rb +38 -0
  159. data/spec/rattler/parsers/combinator_parser_spec.rb +14 -0
  160. data/spec/rattler/parsers/direct_action_spec.rb +16 -2
  161. data/spec/rattler/parsers/dispatch_action_spec.rb +15 -32
  162. data/spec/rattler/parsers/fail_spec.rb +6 -4
  163. data/spec/rattler/parsers/label_spec.rb +10 -28
  164. data/spec/rattler/parsers/node_code_spec.rb +48 -0
  165. data/spec/rattler/parsers/parser_dsl_spec.rb +1 -1
  166. data/spec/rattler/parsers/rule_set_spec.rb +35 -0
  167. data/spec/rattler/parsers/sequence_spec.rb +15 -24
  168. data/spec/rattler/runtime/extended_packrat_parser_spec.rb +22 -17
  169. data/spec/rattler/runtime/packrat_parser_spec.rb +1 -1
  170. data/spec/rattler/runtime/parse_node_spec.rb +15 -19
  171. data/spec/rattler/runtime/recursive_descent_parser_spec.rb +1 -1
  172. data/spec/rattler/runtime/shared_parser_examples.rb +61 -28
  173. data/spec/rattler/util/graphviz/node_builder_spec.rb +84 -0
  174. data/spec/rattler/util/node_spec.rb +92 -65
  175. data/spec/rattler_spec.rb +16 -16
  176. data/spec/support/combinator_parser_spec_helper.rb +19 -18
  177. data/spec/support/compiler_spec_helper.rb +56 -87
  178. data/spec/support/runtime_parser_spec_helper.rb +6 -14
  179. metadata +117 -22
  180. data/features/grammar/regex.feature +0 -24
  181. data/lib/rattler/parsers/match_joining.rb +0 -67
  182. data/lib/rattler/parsers/rules.rb +0 -43
@@ -4,20 +4,20 @@ module Rattler::BackEnd::ParserGenerator
4
4
  # @private
5
5
  module PredicatePropogating #:nodoc:
6
6
 
7
- def gen_assert(parser)
8
- generate parser.child, :assert
7
+ def gen_assert(parser, scope={})
8
+ generate parser.child, :assert, scope
9
9
  end
10
10
 
11
- def gen_disallow(parser)
12
- generate parser.child, :disallow
11
+ def gen_disallow(parser, scope={})
12
+ generate parser.child, :disallow, scope
13
13
  end
14
14
 
15
- def gen_intermediate_assert(parser)
16
- generate parser.child, :intermediate_assert
15
+ def gen_intermediate_assert(parser, scope={})
16
+ generate parser.child, :intermediate_assert, scope
17
17
  end
18
18
 
19
- def gen_intermediate_disallow(parser)
20
- generate parser.child, :intermediate_disallow
19
+ def gen_intermediate_disallow(parser, scope={})
20
+ generate parser.child, :intermediate_disallow, scope
21
21
  end
22
22
 
23
23
  end
@@ -4,60 +4,58 @@ module Rattler::BackEnd::ParserGenerator
4
4
  # @private
5
5
  module RepeatGenerating #:nodoc:
6
6
 
7
- def gen_basic_nested(repeat)
8
- atomic_block { gen_basic_top_level repeat }
7
+ def gen_basic_nested(repeat, scope={})
8
+ atomic_block { gen_basic_top_level repeat, scope }
9
9
  end
10
10
 
11
- def gen_basic_top_level(repeat)
11
+ def gen_basic_top_level(repeat, scope={})
12
12
  if repeat.capturing?
13
- gen_loop repeat, :basic_nested
13
+ gen_loop repeat, :basic_nested, scope
14
14
  gen_result accumulator_name
15
15
  else
16
- gen_skip_top_level repeat
16
+ gen_skip_top_level repeat, scope
17
17
  end
18
18
  end
19
19
 
20
- def gen_dispatch_action_nested(repeat, target, method_name)
20
+ def gen_dispatch_action_nested(repeat, code, scope={})
21
21
  atomic_block do
22
- gen_dispatch_action_top_level repeat, target, method_name
22
+ gen_dispatch_action_top_level repeat, code, scope
23
23
  end
24
24
  end
25
25
 
26
- def gen_dispatch_action_top_level(repeat, target, method_name)
27
- gen_loop repeat
28
- gen_result dispatch_action_result(target, method_name,
29
- :array_expr => "select_captures(#{accumulator_name})")
26
+ def gen_dispatch_action_top_level(repeat, code, scope={})
27
+ gen_loop repeat, :basic, scope
28
+ gen_result code.bind(scope, "select_captures(#{accumulator_name})")
30
29
  end
31
30
 
32
- def gen_direct_action_nested(repeat, action)
33
- atomic_block { gen_direct_action_top_level repeat, action }
31
+ def gen_direct_action_nested(repeat, code, scope={})
32
+ atomic_block { gen_direct_action_top_level repeat, code, scope }
34
33
  end
35
34
 
36
- def gen_direct_action_top_level(repeat, action)
37
- gen_loop repeat
38
- gen_result direct_action_result(action,
39
- :bind_args => ["select_captures(#{accumulator_name})"])
35
+ def gen_direct_action_top_level(repeat, code, scope={})
36
+ gen_loop repeat, :basic, scope
37
+ gen_result('(' + code.bind(scope, ["select_captures(#{accumulator_name})"]) + ')')
40
38
  end
41
39
 
42
- def gen_token_nested(repeat)
43
- atomic_block { gen_token_top_level repeat }
40
+ def gen_token_nested(repeat, scope={})
41
+ atomic_block { gen_token_top_level repeat, scope }
44
42
  end
45
43
 
46
- def gen_token_top_level(repeat)
47
- gen_loop repeat, :token
44
+ def gen_token_top_level(repeat, scope={})
45
+ gen_loop repeat, :token, scope
48
46
  gen_result "#{accumulator_name}.join"
49
47
  end
50
48
 
51
- def gen_skip_nested(repeat)
52
- atomic_block { gen_skip_top_level repeat }
49
+ def gen_skip_nested(repeat, scope={})
50
+ atomic_block { gen_skip_top_level repeat, scope }
53
51
  end
54
52
 
55
53
  private
56
54
 
57
- def gen_loop(repeat, child_as = :basic)
55
+ def gen_loop(repeat, child_as = :basic, scope={})
58
56
  (@g << "#{accumulator_name} = []").newline
59
57
  @g << "while #{result_name} = "
60
- generate repeat.child, child_as
58
+ generate repeat.child, child_as, scope
61
59
  @g.block('') { @g << "#{accumulator_name} << #{result_name}" }.newline
62
60
  end
63
61
 
@@ -3,103 +3,51 @@ require 'rattler/back_end/parser_generator'
3
3
  module Rattler::BackEnd::ParserGenerator
4
4
  # @private
5
5
  class RuleGenerator #:nodoc:
6
-
6
+
7
7
  Grammar = Rattler::Grammar::Grammar
8
8
  include Rattler::Parsers
9
-
9
+
10
10
  def initialize(g)
11
11
  @g = g
12
12
  @top_level_generator = TopLevelGenerator.new(@g)
13
13
  end
14
-
15
- def generate(parser)
14
+
15
+ def generate(parser, opts={})
16
16
  case parser
17
- when Grammar then gen_parser parser
18
- when Rules then gen_rules parser
19
- when Rule then gen_rule parser
17
+ when Rule then gen_rule_modular parser
20
18
  else @top_level_generator.generate parser
21
19
  end
22
20
  self
23
21
  end
24
-
25
- private
26
-
27
- def gen_parser(grammar)
28
- gen_requires grammar.requires
29
- gen_module(grammar) do
30
- gen_includes grammar.includes
31
- generate grammar.rules
32
- end
33
- end
34
-
35
- def gen_requires(requires)
36
- requires.each {|_| (@g << "require #{_}").newline }
37
- @g.newline
38
- end
39
-
40
- def gen_module(grammar)
41
- if grammar.grammar_name
42
- gen_grammar_def(grammar.grammar_name) { yield }
43
- elsif grammar.parser_name
44
- gen_parser_def(grammar.parser_name, grammar.base_name) { yield }
22
+
23
+ def gen_rule_standalone(rule, rule_set)
24
+ if rule_set.analysis.left_recursive? rule.name
25
+ gen_rule_hook rule, 'memoize_lr'
26
+ elsif rule_set.analysis.recursive? rule.name
27
+ gen_rule_hook rule, 'memoize'
45
28
  else
46
- yield
47
- end
48
- end
49
-
50
- def gen_includes(includes)
51
- unless includes.empty?
52
- includes.each {|_| (@g << "include #{_}").newline }
53
- @g.newline
29
+ gen_rule_method rule, "match_#{rule.name}"
54
30
  end
55
31
  end
56
-
57
- def gen_rules(rules)
58
- gen_start_rule rules.start_rule if rules.start_rule
59
- @g.intersperse(rules, :newlines => 2) {|_| generate _ }
32
+
33
+ def gen_rule_modular(rule)
34
+ gen_rule_hook rule, 'apply'
60
35
  end
61
-
62
- def gen_start_rule(start_rule)
36
+
37
+ private
38
+
39
+ def gen_rule_hook(rule, hook_name)
63
40
  (@g << "# @private").newline
64
- @g.block('def start_rule #:nodoc:') { @g << ":#{start_rule}"}.newline
65
- @g.newline
41
+ @g.block("def match_#{rule.name} #:nodoc:") do
42
+ @g << "#{hook_name} :match_#{rule.name}!"
43
+ end.newline.newline
44
+ gen_rule_method rule, "match_#{rule.name}!"
66
45
  end
67
-
68
- def gen_rule(rule)
46
+
47
+ def gen_rule_method(rule, method_name)
69
48
  (@g << "# @private").newline
70
- @g.block("def match_#{rule.name} #:nodoc:") { generate rule.child }
71
- end
72
-
73
- def gen_grammar_def(grammar_name)
74
- nest_modules(grammar_name.split('::')) do |name|
75
- (@g << "# @private").newline
76
- module_block("module #{name} #:nodoc:") { yield }
77
- end
78
- end
79
-
80
- def gen_parser_def(parser_name, base_name)
81
- nest_modules(parser_name.split('::')) do |name|
82
- (@g << "# @private").newline
83
- module_block("class #{name} < #{base_name} #:nodoc:") { yield }
84
- end
49
+ @g.block("def #{method_name} #:nodoc:") { generate rule.child }
85
50
  end
86
-
87
- def nest_modules(path)
88
- mod, *rest = path
89
- if rest.empty?
90
- yield mod
91
- else
92
- @g.block("module #{mod}") { nest_modules(rest) {|_| yield _ } }
93
- end
94
- end
95
-
96
- def module_block(decl)
97
- @g.block(decl) do
98
- @g.newline
99
- yield
100
- @g.newline
101
- end
102
- end
103
-
51
+
104
52
  end
105
53
  end
@@ -0,0 +1,102 @@
1
+ require 'rattler/back_end/parser_generator'
2
+
3
+ module Rattler::BackEnd::ParserGenerator
4
+ # @private
5
+ class RuleSetGenerator #:nodoc:
6
+
7
+ Grammar = Rattler::Grammar::Grammar
8
+ include Rattler::Parsers
9
+
10
+ def initialize(g)
11
+ @g = g
12
+ @rule_generator = RuleGenerator.new(@g)
13
+ end
14
+
15
+ def generate(parser, opts={})
16
+ case parser
17
+ when Grammar then gen_parser parser, opts
18
+ when RuleSet then gen_rules parser, opts
19
+ end
20
+ self
21
+ end
22
+
23
+ def gen_parser(grammar, opts={})
24
+ gen_requires grammar.requires
25
+ gen_module(grammar) do
26
+ gen_includes grammar.includes
27
+ gen_rules grammar.rules, opts
28
+ end
29
+ end
30
+
31
+ def gen_requires(requires)
32
+ requires.each {|_| (@g << "require #{_}").newline }
33
+ @g.newline
34
+ end
35
+
36
+ def gen_module(grammar)
37
+ if grammar.grammar_name
38
+ gen_grammar_def(grammar.grammar_name) { yield }
39
+ elsif grammar.parser_name
40
+ gen_parser_def(grammar.parser_name, grammar.base_name) { yield }
41
+ else
42
+ yield
43
+ end
44
+ end
45
+
46
+ def gen_includes(includes)
47
+ unless includes.empty?
48
+ includes.each {|_| (@g << "include #{_}").newline }
49
+ @g.newline
50
+ end
51
+ end
52
+
53
+ def gen_rules(rules, opts={})
54
+ gen_start_rule rules.start_rule if rules.start_rule
55
+ @g.intersperse(rules, :newlines => 2) do |rule|
56
+ if opts[:standalone]
57
+ @rule_generator.gen_rule_standalone rule, rules
58
+ else
59
+ @rule_generator.gen_rule_modular rule
60
+ end
61
+ end
62
+ end
63
+
64
+ def gen_start_rule(start_rule)
65
+ (@g << "# @private").newline
66
+ @g.block('def start_rule #:nodoc:') { @g << ":#{start_rule}"}.newline
67
+ @g.newline
68
+ end
69
+
70
+ def gen_grammar_def(grammar_name)
71
+ nest_modules(grammar_name.split('::')) do |name|
72
+ (@g << "# @private").newline
73
+ module_block("module #{name} #:nodoc:") { yield }
74
+ end
75
+ end
76
+
77
+ def gen_parser_def(parser_name, base_name)
78
+ nest_modules(parser_name.split('::')) do |name|
79
+ (@g << "# @private").newline
80
+ module_block("class #{name} < #{base_name} #:nodoc:") { yield }
81
+ end
82
+ end
83
+
84
+ def nest_modules(path)
85
+ mod, *rest = path
86
+ if rest.empty?
87
+ yield mod
88
+ else
89
+ @g.block("module #{mod}") { nest_modules(rest) {|_| yield _ } }
90
+ end
91
+ end
92
+
93
+ def module_block(decl)
94
+ @g.block(decl) do
95
+ @g.newline
96
+ yield
97
+ @g.newline
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -13,32 +13,34 @@ module Rattler::BackEnd::ParserGenerator
13
13
  @capture_names = []
14
14
  end
15
15
 
16
- def gen_basic_nested(sequence)
17
- atomic_block { gen_basic_top_level sequence }
16
+ def gen_basic_nested(sequence, scope={})
17
+ atomic_block { gen_basic_top_level sequence, scope }
18
18
  end
19
19
 
20
- def gen_basic_top_level(sequence)
20
+ def gen_basic_top_level(sequence, scope={})
21
21
  with_backtracking do
22
22
  if sequence.capture_count == 1 and sequence.children.last.capturing?
23
23
  @g.intersperse_nl(sequence, ' &&') do |child|
24
- gen_capturing(child) { generate child }
24
+ scope = gen_capturing(child, scope) { generate child, :basic, scope }
25
25
  end
26
26
  else
27
- sequence.each { |_| @g.suffix(' &&') { gen_capturing _ }.newline }
27
+ sequence.each do |child|
28
+ @g.suffix(' &&') { scope = gen_capturing child, scope }.newline
29
+ end
28
30
  @g << result_expr(sequence)
29
31
  end
30
32
  end
31
33
  end
32
34
 
33
- def gen_assert_nested(sequence)
34
- atomic_block { gen_assert_top_level sequence }
35
+ def gen_assert_nested(sequence, scope={})
36
+ atomic_block { gen_assert_top_level sequence, scope }
35
37
  end
36
38
 
37
- def gen_assert_top_level(sequence)
39
+ def gen_assert_top_level(sequence, scope={})
38
40
  lookahead do
39
41
  @g.block("#{result_name} = begin") do
40
42
  sequence.each do |_|
41
- @g.suffix(' &&') { generate _, :intermediate_skip }.newline
43
+ @g.suffix(' &&') { scope = gen_matching _, scope }.newline
42
44
  end
43
45
  @g << "true"
44
46
  end
@@ -47,15 +49,15 @@ module Rattler::BackEnd::ParserGenerator
47
49
  @g << result_name
48
50
  end
49
51
 
50
- def gen_disallow_nested(sequence)
51
- atomic_block { gen_disallow_top_level sequence }
52
+ def gen_disallow_nested(sequence, scope={})
53
+ atomic_block { gen_disallow_top_level sequence, scope }
52
54
  end
53
55
 
54
- def gen_disallow_top_level(sequence)
56
+ def gen_disallow_top_level(sequence, scope={})
55
57
  lookahead do
56
58
  @g.block("#{result_name} = !begin") do
57
59
  @g.intersperse_nl(sequence, ' &&') do |_|
58
- generate _, :intermediate_skip
60
+ scope = gen_matching _, scope
59
61
  end
60
62
  end
61
63
  @g.newline
@@ -63,51 +65,49 @@ module Rattler::BackEnd::ParserGenerator
63
65
  @g << result_name
64
66
  end
65
67
 
66
- def gen_dispatch_action_nested(sequence, target, method_name)
68
+ def gen_dispatch_action_nested(sequence, code, scope={})
67
69
  atomic_block do
68
- gen_dispatch_action_top_level sequence, target, method_name
70
+ gen_dispatch_action_top_level sequence, code, scope
69
71
  end
70
72
  end
71
73
 
72
- def gen_dispatch_action_top_level(sequence, target, method_name)
73
- gen_action_code(sequence) do |labeled|
74
- dispatch_action_result(target, method_name,
75
- :array_expr => result_array_expr(sequence), :labeled => labeled)
74
+ def gen_dispatch_action_top_level(sequence, code, scope={})
75
+ gen_action_code(sequence, scope) do |new_scope|
76
+ code.bind new_scope, result_array_expr(sequence)
76
77
  end
77
78
  end
78
79
 
79
- def gen_direct_action_nested(sequence, action)
80
- atomic_block { gen_direct_action_top_level sequence, action }
80
+ def gen_direct_action_nested(sequence, code, scope={})
81
+ atomic_block { gen_direct_action_top_level sequence, code, scope }
81
82
  end
82
83
 
83
- def gen_direct_action_top_level(sequence, action)
84
- gen_action_code(sequence) do |labeled|
85
- direct_action_result(action,
86
- :bind_args => @capture_names, :labeled => labeled)
84
+ def gen_direct_action_top_level(sequence, code, scope={})
85
+ gen_action_code(sequence, scope) do |new_scope|
86
+ "(#{code.bind new_scope, @capture_names})"
87
87
  end
88
88
  end
89
89
 
90
- def gen_token_nested(sequence)
91
- atomic_block { gen_token_top_level sequence }
90
+ def gen_token_nested(sequence, scope={})
91
+ atomic_block { gen_token_top_level sequence, scope }
92
92
  end
93
93
 
94
- def gen_token_top_level(sequence)
94
+ def gen_token_top_level(sequence, scope={})
95
95
  with_backtracking do
96
96
  sequence.each do |_|
97
- @g.suffix(' &&') { generate _, :intermediate_skip }.newline
97
+ @g.suffix(' &&') { scope = gen_matching _, scope }.newline
98
98
  end
99
99
  @g << "@scanner.string[#{saved_pos_name}...(@scanner.pos)]"
100
100
  end
101
101
  end
102
102
 
103
- def gen_skip_nested(sequence)
104
- atomic_block { gen_skip_top_level sequence }
103
+ def gen_skip_nested(sequence, scope={})
104
+ atomic_block { gen_skip_top_level sequence, scope }
105
105
  end
106
106
 
107
- def gen_skip_top_level(sequence)
107
+ def gen_skip_top_level(sequence, scope={})
108
108
  with_backtracking do
109
109
  sequence.each do |_|
110
- @g.suffix(' &&') { generate _, :intermediate_skip }.newline
110
+ @g.suffix(' &&') { scope = gen_matching _, scope }.newline
111
111
  end
112
112
  @g << "true"
113
113
  end
@@ -115,16 +115,26 @@ module Rattler::BackEnd::ParserGenerator
115
115
 
116
116
  private
117
117
 
118
- def gen_capturing(child)
118
+ def gen_matching(child, scope)
119
+ if child.labeled?
120
+ @g.surround("(#{capture_name} = ", ')') { generate child, :basic, scope }
121
+ else
122
+ generate child, :intermediate_skip, scope
123
+ end
124
+ child.labeled? ? scope.merge(child.label => last_capture_name) : scope
125
+ end
126
+
127
+ def gen_capturing(child, scope)
119
128
  if child.capturing?
120
129
  if block_given?
121
130
  yield
122
131
  else
123
- @g.surround("(#{capture_name} = ", ')') { generate child }
132
+ @g.surround("(#{capture_name} = ", ')') { generate child, :basic, scope }
124
133
  end
125
134
  else
126
- generate child, :intermediate
135
+ generate child, :intermediate, scope
127
136
  end
137
+ child.labeled? ? scope.merge(child.label => last_capture_name) : scope
128
138
  end
129
139
 
130
140
  def with_backtracking
@@ -153,14 +163,12 @@ module Rattler::BackEnd::ParserGenerator
153
163
  end
154
164
  end
155
165
 
156
- def gen_action_code(sequence)
166
+ def gen_action_code(sequence, scope={})
157
167
  with_backtracking do
158
- labeled = {}
159
168
  for child in sequence
160
- @g.suffix(' &&') { gen_capturing child }.newline
161
- labeled[child.label] = last_capture_name if child.labeled?
169
+ @g.suffix(' &&') { scope = gen_capturing child, scope }.newline
162
170
  end
163
- @g << yield(labeled)
171
+ @g << yield(scope)
164
172
  end
165
173
  end
166
174