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.
- data/README.rdoc +57 -37
- data/features/command_line/dest_option.feature +8 -21
- data/features/command_line/lib_option.feature +37 -0
- data/features/command_line/parser_generator.feature +7 -4
- data/features/grammar/back_reference.feature +37 -0
- data/features/grammar/fail.feature +3 -3
- data/features/grammar/labels.feature +11 -3
- data/features/grammar/list_matching.feature +14 -5
- data/features/grammar/literal.feature +30 -4
- data/features/grammar/nonterminal.feature +1 -1
- data/features/grammar/ordered_choice.feature +2 -2
- data/features/grammar/skip_operator.feature +1 -1
- data/features/grammar/symantic_action.feature +7 -7
- data/features/grammar/whitespace.feature +2 -2
- data/features/step_definitions/grammar_steps.rb +2 -2
- data/lib/rattler/back_end.rb +1 -0
- data/lib/rattler/back_end/compiler.rb +19 -20
- data/lib/rattler/back_end/optimizer.rb +100 -0
- data/lib/rattler/back_end/optimizer/composite_reducing.rb +18 -0
- data/lib/rattler/back_end/optimizer/flatten_choice.rb +31 -0
- data/lib/rattler/back_end/optimizer/flatten_sequence.rb +59 -0
- data/lib/rattler/back_end/optimizer/flattening.rb +17 -0
- data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +46 -0
- data/lib/rattler/back_end/optimizer/join_match_capturing_sequence.rb +71 -0
- data/lib/rattler/back_end/optimizer/join_match_choice.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_match_matching_sequence.rb +38 -0
- data/lib/rattler/back_end/optimizer/join_match_sequence.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_nested_match.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_nested_match.rb +36 -0
- data/lib/rattler/back_end/optimizer/match_joining.rb +60 -0
- data/lib/rattler/back_end/optimizer/optimization.rb +94 -0
- data/lib/rattler/back_end/optimizer/optimization_context.rb +72 -0
- data/lib/rattler/back_end/optimizer/optimization_sequence.rb +37 -0
- data/lib/rattler/back_end/optimizer/optimize_children.rb +46 -0
- data/lib/rattler/back_end/optimizer/reduce_repeat_match.rb +44 -0
- data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +32 -0
- data/lib/rattler/back_end/optimizer/simplify_redundant_repeat.rb +43 -0
- data/lib/rattler/back_end/optimizer/simplify_token_match.rb +38 -0
- data/lib/rattler/back_end/parser_generator.rb +21 -14
- data/lib/rattler/back_end/parser_generator/apply_generator.rb +35 -35
- data/lib/rattler/back_end/parser_generator/assert_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/back_reference_generator.rb +93 -0
- data/lib/rattler/back_end/parser_generator/choice_generator.rb +33 -49
- data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +14 -14
- data/lib/rattler/back_end/parser_generator/disallow_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +11 -13
- data/lib/rattler/back_end/parser_generator/expr_generator.rb +36 -56
- data/lib/rattler/back_end/parser_generator/fail_generator.rb +18 -18
- data/lib/rattler/back_end/parser_generator/group_match.rb +18 -0
- data/lib/rattler/back_end/parser_generator/group_match_generator.rb +76 -0
- data/lib/rattler/back_end/parser_generator/label_generator.rb +25 -6
- data/lib/rattler/back_end/parser_generator/list1_generator.rb +7 -7
- data/lib/rattler/back_end/parser_generator/list_generating.rb +19 -20
- data/lib/rattler/back_end/parser_generator/list_generator.rb +5 -5
- data/lib/rattler/back_end/parser_generator/match_generator.rb +52 -52
- data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +6 -6
- data/lib/rattler/back_end/parser_generator/optional_generator.rb +30 -29
- data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +8 -8
- data/lib/rattler/back_end/parser_generator/repeat_generating.rb +23 -25
- data/lib/rattler/back_end/parser_generator/rule_generator.rb +27 -79
- data/lib/rattler/back_end/parser_generator/rule_set_generator.rb +102 -0
- data/lib/rattler/back_end/parser_generator/sequence_generator.rb +49 -41
- data/lib/rattler/back_end/parser_generator/skip_generator.rb +14 -20
- data/lib/rattler/back_end/parser_generator/skip_propogating.rb +4 -4
- data/lib/rattler/back_end/parser_generator/sub_generating.rb +6 -0
- data/lib/rattler/back_end/parser_generator/token_generator.rb +12 -12
- data/lib/rattler/back_end/parser_generator/token_propogating.rb +2 -2
- data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +4 -4
- data/lib/rattler/grammar.rb +4 -3
- data/lib/rattler/grammar/analysis.rb +91 -0
- data/lib/rattler/grammar/grammar.rb +37 -25
- data/lib/rattler/grammar/grammar_parser.rb +19 -11
- data/lib/rattler/grammar/metagrammar.rb +569 -800
- data/lib/rattler/grammar/rattler.rtlr +162 -144
- data/lib/rattler/parsers.rb +5 -1
- data/lib/rattler/parsers/action_code.rb +29 -15
- data/lib/rattler/parsers/apply.rb +5 -5
- data/lib/rattler/parsers/assert.rb +4 -18
- data/lib/rattler/parsers/back_reference.rb +46 -0
- data/lib/rattler/parsers/choice.rb +6 -39
- data/lib/rattler/parsers/combinator_parser.rb +32 -0
- data/lib/rattler/parsers/combining.rb +3 -29
- data/lib/rattler/parsers/direct_action.rb +27 -30
- data/lib/rattler/parsers/disallow.rb +4 -18
- data/lib/rattler/parsers/dispatch_action.rb +30 -25
- data/lib/rattler/parsers/label.rb +9 -18
- data/lib/rattler/parsers/list.rb +3 -34
- data/lib/rattler/parsers/list1.rb +4 -36
- data/lib/rattler/parsers/list_parser.rb +64 -0
- data/lib/rattler/parsers/match.rb +7 -42
- data/lib/rattler/parsers/node_code.rb +44 -0
- data/lib/rattler/parsers/one_or_more.rb +7 -27
- data/lib/rattler/parsers/optional.rb +5 -25
- data/lib/rattler/parsers/parser.rb +16 -44
- data/lib/rattler/parsers/parser_dsl.rb +13 -3
- data/lib/rattler/parsers/predicate.rb +4 -12
- data/lib/rattler/parsers/rule.rb +18 -19
- data/lib/rattler/parsers/rule_set.rb +63 -0
- data/lib/rattler/parsers/sequence.rb +12 -46
- data/lib/rattler/parsers/skip.rb +12 -26
- data/lib/rattler/parsers/token.rb +6 -21
- data/lib/rattler/parsers/zero_or_more.rb +6 -26
- data/lib/rattler/runner.rb +66 -28
- data/lib/rattler/runtime/extended_packrat_parser.rb +26 -20
- data/lib/rattler/runtime/packrat_parser.rb +17 -21
- data/lib/rattler/runtime/parser.rb +12 -2
- data/lib/rattler/runtime/recursive_descent_parser.rb +3 -11
- data/lib/rattler/util.rb +2 -1
- data/lib/rattler/util/graphviz.rb +29 -0
- data/lib/rattler/util/graphviz/digraph_builder.rb +71 -0
- data/lib/rattler/util/graphviz/node_builder.rb +84 -0
- data/lib/rattler/util/node.rb +37 -19
- data/lib/rattler/util/parser_spec_helper.rb +61 -35
- data/spec/rattler/back_end/compiler_spec.rb +6 -860
- data/spec/rattler/back_end/optimizer/flatten_choice_spec.rb +70 -0
- data/spec/rattler/back_end/optimizer/flatten_sequence_spec.rb +130 -0
- data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +80 -0
- data/spec/rattler/back_end/optimizer/join_match_capturing_sequence_spec.rb +241 -0
- data/spec/rattler/back_end/optimizer/join_match_choice_spec.rb +100 -0
- data/spec/rattler/back_end/optimizer/join_match_matching_sequence_spec.rb +112 -0
- data/spec/rattler/back_end/optimizer/join_predicate_bare_match_spec.rb +194 -0
- data/spec/rattler/back_end/optimizer/join_predicate_nested_match_spec.rb +180 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_bare_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_nested_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb +98 -0
- data/spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb +226 -0
- data/spec/rattler/back_end/optimizer/simplify_token_match_spec.rb +85 -0
- data/spec/rattler/back_end/parser_generator/apply_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/assert_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb +181 -0
- data/spec/rattler/back_end/parser_generator/choice_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/disallow_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +185 -0
- data/spec/rattler/back_end/parser_generator/label_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/match_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/one_or_more_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/optional_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/rule_generator_spec.rb +13 -46
- data/spec/rattler/back_end/parser_generator/rule_set_generator_spec.rb +97 -0
- data/spec/rattler/back_end/parser_generator/sequence_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/skip_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/token_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/zero_or_more_generator_spec.rb +39 -34
- data/spec/rattler/back_end/shared_compiler_examples.rb +885 -0
- data/spec/rattler/grammar/analysis_spec.rb +167 -0
- data/spec/rattler/grammar/grammar_parser_spec.rb +169 -179
- data/spec/rattler/grammar/grammar_spec.rb +24 -21
- data/spec/rattler/parsers/action_code_spec.rb +64 -19
- data/spec/rattler/parsers/apply_spec.rb +9 -9
- data/spec/rattler/parsers/back_reference_spec.rb +38 -0
- data/spec/rattler/parsers/combinator_parser_spec.rb +14 -0
- data/spec/rattler/parsers/direct_action_spec.rb +16 -2
- data/spec/rattler/parsers/dispatch_action_spec.rb +15 -32
- data/spec/rattler/parsers/fail_spec.rb +6 -4
- data/spec/rattler/parsers/label_spec.rb +10 -28
- data/spec/rattler/parsers/node_code_spec.rb +48 -0
- data/spec/rattler/parsers/parser_dsl_spec.rb +1 -1
- data/spec/rattler/parsers/rule_set_spec.rb +35 -0
- data/spec/rattler/parsers/sequence_spec.rb +15 -24
- data/spec/rattler/runtime/extended_packrat_parser_spec.rb +22 -17
- data/spec/rattler/runtime/packrat_parser_spec.rb +1 -1
- data/spec/rattler/runtime/parse_node_spec.rb +15 -19
- data/spec/rattler/runtime/recursive_descent_parser_spec.rb +1 -1
- data/spec/rattler/runtime/shared_parser_examples.rb +61 -28
- data/spec/rattler/util/graphviz/node_builder_spec.rb +84 -0
- data/spec/rattler/util/node_spec.rb +92 -65
- data/spec/rattler_spec.rb +16 -16
- data/spec/support/combinator_parser_spec_helper.rb +19 -18
- data/spec/support/compiler_spec_helper.rb +56 -87
- data/spec/support/runtime_parser_spec_helper.rb +6 -14
- metadata +117 -22
- data/features/grammar/regex.feature +0 -24
- data/lib/rattler/parsers/match_joining.rb +0 -67
- data/lib/rattler/parsers/rules.rb +0 -43
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/join_predicate_or_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 Choice can be
|
12
|
+
# joined into a single skip of a Regexp match.
|
13
|
+
#
|
14
|
+
# @author Jason Arhart
|
15
|
+
#
|
16
|
+
class JoinPredicateOrNestedMatch < JoinPredicateOrBareMatch
|
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 super parser.child
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rattler'
|
2
|
+
|
3
|
+
module Rattler::BackEnd::Optimizer
|
4
|
+
# @private
|
5
|
+
module MatchJoining #:nodoc:
|
6
|
+
|
7
|
+
include CompositeReducing
|
8
|
+
|
9
|
+
include Rattler::Parsers
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def _applies_to?(parser, context)
|
14
|
+
any_neighbors?(parser) {|_| eligible_child? _ }
|
15
|
+
end
|
16
|
+
|
17
|
+
def _apply(parser, context)
|
18
|
+
new_children = []
|
19
|
+
matches = []
|
20
|
+
for child in parser
|
21
|
+
if eligible_child? child
|
22
|
+
matches << child
|
23
|
+
else
|
24
|
+
join_matches(matches) {|match| new_children << match }
|
25
|
+
matches = []
|
26
|
+
new_children << child
|
27
|
+
end
|
28
|
+
end
|
29
|
+
join_matches(matches) {|match| new_children << match }
|
30
|
+
finish_reduce parser, new_children
|
31
|
+
end
|
32
|
+
|
33
|
+
def any_neighbors?(parser)
|
34
|
+
parser.each_cons(2).any? {|a| a.all? {|_| yield _ } }
|
35
|
+
end
|
36
|
+
|
37
|
+
def join_matches(matches)
|
38
|
+
unless matches.empty?
|
39
|
+
yield create_match(join_patterns(create_patterns(matches)))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_patterns(matches)
|
44
|
+
matches.map {|_| create_pattern _ }
|
45
|
+
end
|
46
|
+
|
47
|
+
def join_patterns(patterns)
|
48
|
+
patterns.join
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_pattern(match)
|
52
|
+
match.re.source
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_match(pattern)
|
56
|
+
Match[Regexp.new(pattern)]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/optimization.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
require 'singleton'
|
9
|
+
|
10
|
+
module Rattler::BackEnd::Optimizer
|
11
|
+
#
|
12
|
+
# An +Optimization+ represents a simple transformation of a parser model into
|
13
|
+
# an equivalent model that can result in more efficient parsing code.
|
14
|
+
# Subclasses override <tt>#_applies_to?</tt> and <tt>#_apply</tt> to define
|
15
|
+
# an optimization.
|
16
|
+
#
|
17
|
+
# @author Jason Arhart
|
18
|
+
#
|
19
|
+
class Optimization
|
20
|
+
|
21
|
+
class <<self
|
22
|
+
def instance
|
23
|
+
@instance ||= self.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# @see Rattler::BackEnd::Optimizer::Optimization#>>
|
27
|
+
def >>(other)
|
28
|
+
instance >> (other.respond_to?(:instance) ? other.instance : other)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @see Rattler::BackEnd::Optimizer::Optimization#match
|
32
|
+
def apply(*args)
|
33
|
+
instance.apply(*args)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @see Rattler::BackEnd::Optimizer::Optimization#applies_to?
|
37
|
+
def applies_to?(*args)
|
38
|
+
instance.applies_to?(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
@applies_to_cache = Hash.new {|h, k| h[k] = {} }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return a new optimzation that sequences this optimzation and +other+,
|
47
|
+
# i.e. the new optimzation applies this optimzation, then applies +other+
|
48
|
+
# to the result.
|
49
|
+
#
|
50
|
+
# @param [Rattler::BackEnd::Optimizer::Optimization] other the optimization
|
51
|
+
# to apply after this one
|
52
|
+
#
|
53
|
+
# @return [Rattler::BackEnd::Optimizer::Optimization] a new optimzation
|
54
|
+
# that sequences this optimzation and +other+
|
55
|
+
def >>(other)
|
56
|
+
OptimizationSequence.new(self, other)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Apply the optimzation to +parser+ in +context+ if
|
60
|
+
# <tt>#applies_to?(parser, context)</tt> is +true+.
|
61
|
+
#
|
62
|
+
# @param [Rattler::Parsers::Parser] parser the parser to be optimized
|
63
|
+
# @param [Rattler::BackEnd::Optimizer::OptimizationContext] context
|
64
|
+
#
|
65
|
+
# @return [Rattler::Parsers::Parser] the optimized parser
|
66
|
+
def apply(parser, context)
|
67
|
+
applies_to?(parser, context) ? _apply(parser, context) : parser
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return +true+ if this optimzation applies to +parser+ in +context+.
|
71
|
+
#
|
72
|
+
# @param [Rattler::Parsers::Parser] parser a parser model
|
73
|
+
# @param [Rattler::BackEnd::Optimizer::OptimizationContext] context
|
74
|
+
#
|
75
|
+
# @return [Boolean] +true+ if this optimzation applies to +parser+ in
|
76
|
+
# +context+
|
77
|
+
def applies_to?(parser, context)
|
78
|
+
@applies_to_cache[context].fetch(parser) do
|
79
|
+
@applies_to_cache[context][parser] = _applies_to?(parser, context)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def optimize(parser, context)
|
86
|
+
optimizations.apply(parser, context)
|
87
|
+
end
|
88
|
+
|
89
|
+
def optimizations
|
90
|
+
::Rattler::BackEnd::Optimizer.optimizations
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/optimization_context.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler/back_end/optimizer'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# +OptimizationContext+ provides contextual information to optimzations.
|
12
|
+
#
|
13
|
+
# @author Jason Arhart
|
14
|
+
#
|
15
|
+
class OptimizationContext
|
16
|
+
|
17
|
+
@@cache = Hash.new {|h, attrs| h[attrs] = self.new(attrs) }
|
18
|
+
|
19
|
+
def self.[](attrs)
|
20
|
+
@@cache[attrs]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(attrs)
|
24
|
+
@attrs = attrs
|
25
|
+
@rules = @attrs[:rules]
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :type, :rules
|
29
|
+
|
30
|
+
def start_rule
|
31
|
+
rules && rules.start_rule
|
32
|
+
end
|
33
|
+
|
34
|
+
def analysis
|
35
|
+
rules && rules.analysis
|
36
|
+
end
|
37
|
+
|
38
|
+
def capturing?
|
39
|
+
@attrs[:type] == :capturing
|
40
|
+
end
|
41
|
+
|
42
|
+
def matching?
|
43
|
+
@attrs[:type] == :matching
|
44
|
+
end
|
45
|
+
|
46
|
+
def standalone?
|
47
|
+
start_rule && @attrs[:standalone]
|
48
|
+
end
|
49
|
+
|
50
|
+
def relavent?(rule)
|
51
|
+
(not standalone? and not rule.attrs[:inline]) or
|
52
|
+
analysis.referenced?(rule.name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def with(new_attrs)
|
56
|
+
self.class[@attrs.merge new_attrs]
|
57
|
+
end
|
58
|
+
|
59
|
+
def method_missing(symbol, *args)
|
60
|
+
if args.empty? and @attrs.has_key? symbol
|
61
|
+
@attrs[symbol]
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def respond_to?(symbol)
|
68
|
+
super or @attrs.has_key? symbol
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/optimization.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# An +OptimizationSequence+ sequences a pair of optimzations so that applying
|
12
|
+
# the sequence applies the first optimization, then applies the second
|
13
|
+
# optimzation to the result.
|
14
|
+
#
|
15
|
+
# @author Jason Arhart
|
16
|
+
#
|
17
|
+
class OptimizationSequence < Optimization
|
18
|
+
|
19
|
+
def initialize(init, last)
|
20
|
+
super()
|
21
|
+
@init = init
|
22
|
+
@last = last
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def _applies_to?(parser, context)
|
28
|
+
@last.applies_to? parser, context or
|
29
|
+
@init.applies_to? parser, context
|
30
|
+
end
|
31
|
+
|
32
|
+
def _apply(parser, context)
|
33
|
+
@last.apply(@init.apply(parser, context), context)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/flatten_choice.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# Optimizes all of the children of a parser model in the appropriate context.
|
12
|
+
#
|
13
|
+
# @author Jason Arhart
|
14
|
+
#
|
15
|
+
class OptimizeChildren < Optimization
|
16
|
+
|
17
|
+
include Rattler::Parsers
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def _applies_to?(parser, context)
|
22
|
+
!parser.children.empty? and
|
23
|
+
(parser.any? do |_|
|
24
|
+
optimizations.applies_to? _, child_context(parser, context)
|
25
|
+
end)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _apply(parser, context)
|
29
|
+
parser.with_children(parser.map do |_|
|
30
|
+
optimize _, child_context(parser, context)
|
31
|
+
end)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def child_context(parser, context)
|
37
|
+
case parser
|
38
|
+
when Assert, Disallow, Token, Skip
|
39
|
+
context.with :type => :matching
|
40
|
+
else
|
41
|
+
context
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/reduce_repeat_match.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# A repeat of a Regexp match can be reduced to a single Regexp match.
|
12
|
+
#
|
13
|
+
# @author Jason Arhart
|
14
|
+
#
|
15
|
+
class ReduceRepeatMatch < Optimization
|
16
|
+
|
17
|
+
include Rattler::Parsers
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def _applies_to?(parser, context)
|
22
|
+
context.matching? and
|
23
|
+
case parser
|
24
|
+
when ZeroOrMore, OneOrMore, Optional
|
25
|
+
parser.child.is_a?(Match)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def _apply(parser, context)
|
30
|
+
Match[Regexp.new("(?>#{parser.child.re.source})#{suffix parser}")]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def suffix(parser)
|
36
|
+
case parser
|
37
|
+
when ZeroOrMore then '*'
|
38
|
+
when OneOrMore then '+'
|
39
|
+
when Optional then '?'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/remove_meaningless_wrapper.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# Token, skip, and symantic action wrappers only have meaning in a capturing
|
12
|
+
# context.
|
13
|
+
#
|
14
|
+
# @author Jason Arhart
|
15
|
+
#
|
16
|
+
class RemoveMeaninglessWrapper < Optimization
|
17
|
+
|
18
|
+
include Rattler::Parsers
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def _applies_to?(parser, context)
|
23
|
+
context.matching? and
|
24
|
+
[Token, Skip, DispatchAction, DirectAction].any? {|_| parser.is_a? _ }
|
25
|
+
end
|
26
|
+
|
27
|
+
def _apply(parser, context)
|
28
|
+
parser.child
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/simplify_redundant_repeat.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
#
|
11
|
+
# A repeat of a repeat can be simplified to a simple repeat.
|
12
|
+
#
|
13
|
+
# @author Jason Arhart
|
14
|
+
#
|
15
|
+
class SimplifyRedundantRepeat < Optimization
|
16
|
+
|
17
|
+
include Rattler::Parsers
|
18
|
+
|
19
|
+
@@repeat_types = [ZeroOrMore, OneOrMore, Optional]
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def _applies_to?(parser, context)
|
24
|
+
context.matching? and
|
25
|
+
[parser, parser.child].all? {|_| repeat? _ }
|
26
|
+
end
|
27
|
+
|
28
|
+
def _apply(parser, context)
|
29
|
+
if @@repeat_types.any? {|_| parser.is_a?(_) and parser.child.is_a?(_) }
|
30
|
+
parser.child
|
31
|
+
else
|
32
|
+
ZeroOrMore[parser.child.child]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def repeat?(parser)
|
39
|
+
@@repeat_types.any? {|_| parser.is_a? _ }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|