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
@@ -0,0 +1,17 @@
1
+ require 'rattler'
2
+
3
+ module Rattler::BackEnd::Optimizer
4
+ # @private
5
+ module Flattening #:nodoc:
6
+
7
+ def _applies_to?(parser, context)
8
+ parser.any? {|_| eligible_child? _ }
9
+ end
10
+
11
+ def _apply(parser, context)
12
+ children = parser.map {|_| eligible_child?(_) ? _.to_a : [_] }.reduce(:+)
13
+ parser.class.new(children, parser.attrs)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ #
2
+ # = rattler/back_end/optimizer/inline_regular_rules.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # References to regular parse rules can be inlined without affecting how they
12
+ # parse, assuming the referenced rule does not change. This optimization is
13
+ # only applied if the referenced rule is explicitly marked for inlining or
14
+ # the :standalone option is used.
15
+ #
16
+ # @author Jason Arhart
17
+ #
18
+ class InlineRegularRules < Optimization
19
+
20
+ include Rattler::Parsers
21
+
22
+ protected
23
+
24
+ def _applies_to?(parser, context)
25
+ parser.is_a? Apply and
26
+ inlineable? parser.rule_name, context
27
+ end
28
+
29
+ def _apply(parser, context)
30
+ optimize context.rules[parser.rule_name].expr, context
31
+ end
32
+
33
+ private
34
+
35
+ def inlineable?(rule_name, context)
36
+ inline_allowed? rule_name, context and
37
+ context.analysis.regular? rule_name
38
+ end
39
+
40
+ def inline_allowed?(rule_name, context)
41
+ context.standalone? or
42
+ context.rules[rule_name].attrs[:inline]
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_match_capturing_sequence.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # Sequences of Regexp matches can be joined into a single Regexp match using
12
+ # capturing groups if necessary.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinMatchCapturingSequence < Optimization
17
+ include MatchJoining
18
+
19
+ include Rattler::Parsers
20
+ include Rattler::BackEnd::ParserGenerator
21
+
22
+ protected
23
+
24
+ def _applies_to?(parser, context)
25
+ context.capturing? and
26
+ parser.is_a?(Sequence) and
27
+ any_neighbors?(parser) {|_| eligible_child? _ }
28
+ end
29
+
30
+ def eligible_child?(child)
31
+ child.is_a? Match or
32
+ (child.is_a? GroupMatch and child.num_groups == 1) or
33
+ (child.is_a? Skip and child.child.is_a? Match)
34
+ end
35
+
36
+ def create_patterns(parsers)
37
+ num_groups = 0
38
+ patterns = parsers.map do |parser|
39
+ case parser
40
+
41
+ when Match
42
+ num_groups += 1
43
+ "(#{parser.re.source})"
44
+
45
+ when GroupMatch
46
+ num_groups += parser.num_groups
47
+ "(?>#{parser.re.source})"
48
+
49
+ when Skip
50
+ "(?>#{parser.child.re.source})"
51
+
52
+ end
53
+ end
54
+ return {:patterns => patterns, :num_groups => num_groups }
55
+ end
56
+
57
+ def join_patterns(info)
58
+ return info.merge(:pattern => info[:patterns].join)
59
+ end
60
+
61
+ def create_match(info)
62
+ match = super(info[:pattern])
63
+ if info[:num_groups] > 0
64
+ GroupMatch[match, {:num_groups => info[:num_groups]}]
65
+ else
66
+ Skip[match]
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_match_choice.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A choice of Regexp matches can be joined into a single Regexp match without
12
+ # affecting how it parses.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinMatchChoice < Optimization
17
+ include MatchJoining
18
+
19
+ include Rattler::Parsers
20
+
21
+ protected
22
+
23
+ def _applies_to?(parser, context)
24
+ parser.is_a?(Choice) and
25
+ super
26
+ end
27
+
28
+ def join_patterns(patterns)
29
+ patterns.join '|'
30
+ end
31
+
32
+ def eligible_child?(child)
33
+ child.is_a? Match
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_match_matching_sequence.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # Sequences of Regexp matches can be joined into a single Regexp without
12
+ # affecting how they match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinMatchMatchingSequence < Optimization
17
+ include MatchJoining
18
+
19
+ include Rattler::Parsers
20
+
21
+ protected
22
+
23
+ def _applies_to?(parser, context)
24
+ context.matching? and
25
+ parser.is_a?(Sequence) and
26
+ any_neighbors?(parser) {|_| eligible_child? _ }
27
+ end
28
+
29
+ def eligible_child?(child)
30
+ child.is_a? Match
31
+ end
32
+
33
+ def create_pattern(match)
34
+ "(?>#{match.re.source})"
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_match_sequence.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler/back_end/optimizer'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # Sequences of Regexp matches can be joined into a single Regexp match using
12
+ # capturing groups if necessary.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ JoinMatchSequence = JoinMatchMatchingSequence >> JoinMatchCapturingSequence
17
+ end
@@ -0,0 +1,68 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_predicate_bare_match.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A predicate and an adjacent Regexp match in a Sequence can be joined into a
12
+ # single Regexp match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinPredicateBareMatch < Optimization
17
+ include CompositeReducing
18
+
19
+ include Rattler::Parsers
20
+
21
+ protected
22
+
23
+ def _applies_to?(parser, context)
24
+ parser.is_a?(Sequence) and
25
+ parser.children.each_cons(2).any? {|a, b| eligible_pair? a, b }
26
+ end
27
+
28
+ def _apply(parser, context)
29
+ a = []
30
+ parser.each {|_| a << (eligible_pair?(a.last, _) ? reduce(a.pop, _) : _)}
31
+ finish_reduce parser, a
32
+ end
33
+
34
+ def reduce(*pair)
35
+ Match[Regexp.new(pair.map {|_| prepare_pattern _ }.join)]
36
+ end
37
+
38
+ def prepare_pattern(child)
39
+ case child
40
+ when Match then "(?>#{child.re.source})"
41
+ when Assert then "(?=#{child.child.re.source})"
42
+ when Disallow then "(?!#{child.child.re.source})"
43
+ when Eof then "\\z"
44
+ end
45
+ end
46
+
47
+ def eligible_pair?(a, b)
48
+ (eligible_match? a and eligible_predicate? b) or
49
+ (eligible_predicate? a and eligible_match? b)
50
+ end
51
+
52
+ def eligible_match?(parser)
53
+ parser.is_a? Match
54
+ end
55
+
56
+ def eligible_predicate?(parser)
57
+ case parser
58
+ when Eof
59
+ true
60
+ when Assert, Disallow
61
+ parser.child.is_a? Match
62
+ else
63
+ false
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_predicate_match.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler/back_end/optimizer'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A predicate and an adjacent Regexp match in a Sequence can be joined into a
12
+ # single Regexp match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ JoinPredicateMatch = JoinPredicateBareMatch >> JoinPredicateNestedMatch
17
+ end
@@ -0,0 +1,37 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_predicate_nested_match.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A predicate and an adjacent skip of a Regexp match in a Sequence can be
12
+ # joined into a single skip of a Regexp match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinPredicateNestedMatch < JoinPredicateBareMatch
17
+ include CompositeReducing
18
+
19
+ include Rattler::Parsers
20
+
21
+ protected
22
+
23
+ def reduce(*pair)
24
+ pair.find {|_| _.is_a? Skip }.with_child super
25
+ end
26
+
27
+ def prepare_pattern(parser)
28
+ super(parser.is_a?(Skip) ? parser.child : parser)
29
+ end
30
+
31
+ def eligible_match?(parser)
32
+ parser.is_a? Skip and
33
+ super parser.child
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,68 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_predicate_or_bare_match.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A predicate and an adjacent Regexp match in a Choice can be joined into a
12
+ # single Regexp match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ class JoinPredicateOrBareMatch < Optimization
17
+ include CompositeReducing
18
+
19
+ include Rattler::Parsers
20
+
21
+ protected
22
+
23
+ def _applies_to?(parser, context)
24
+ parser.is_a?(Choice) and
25
+ parser.children.each_cons(2).any? {|a, b| eligible_pair? a, b }
26
+ end
27
+
28
+ def _apply(parser, context)
29
+ a = []
30
+ parser.each {|_| a << (eligible_pair?(a.last, _) ? reduce(a.pop, _) : _)}
31
+ finish_reduce parser, a
32
+ end
33
+
34
+ def reduce(*pair)
35
+ Match[Regexp.new(pair.map {|_| prepare_pattern _ }.join '|' )]
36
+ end
37
+
38
+ def prepare_pattern(child)
39
+ case child
40
+ when Match then child.re.source
41
+ when Assert then "(?=#{child.child.re.source})"
42
+ when Disallow then "(?!#{child.child.re.source})"
43
+ when Eof then "\\z"
44
+ end
45
+ end
46
+
47
+ def eligible_pair?(a, b)
48
+ (eligible_match? a and eligible_predicate? b) or
49
+ (eligible_predicate? a and eligible_match? b)
50
+ end
51
+
52
+ def eligible_match?(parser)
53
+ parser.is_a? Match
54
+ end
55
+
56
+ def eligible_predicate?(parser)
57
+ case parser
58
+ when Eof
59
+ true
60
+ when Assert, Disallow
61
+ parser.child.is_a? Match
62
+ else
63
+ false
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ # = rattler/back_end/optimizer/join_predicate_or_match.rb
3
+ #
4
+ # Author:: Jason Arhart
5
+ # Documentation:: Author
6
+ #
7
+ require 'rattler/back_end/optimizer'
8
+
9
+ module Rattler::BackEnd::Optimizer
10
+ #
11
+ # A predicate and an adjacent Regexp match in a Choice can be joined into a
12
+ # single Regexp match.
13
+ #
14
+ # @author Jason Arhart
15
+ #
16
+ JoinPredicateOrMatch = JoinPredicateOrBareMatch >> JoinPredicateOrNestedMatch
17
+ end