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
@@ -1,6 +1,6 @@
|
|
1
1
|
Feature: Ordered Choice Expressions
|
2
2
|
|
3
|
-
An ordered choice expression is a series of sub-expressions separated by "
|
3
|
+
An ordered choice expression is a series of sub-expressions separated by "/"
|
4
4
|
and it means to try each sub-expression in order until one matches, and fail
|
5
5
|
if none of the sub-expressions match.
|
6
6
|
|
@@ -11,7 +11,7 @@ Feature: Ordered Choice Expressions
|
|
11
11
|
Scenario Outline: Parsing
|
12
12
|
Given a grammar with:
|
13
13
|
"""
|
14
|
-
expr <- "A"
|
14
|
+
expr <- "A" / "B"
|
15
15
|
"""
|
16
16
|
When I parse <input>
|
17
17
|
Then the parse result should be <result>
|
@@ -9,7 +9,7 @@ Feature: Skip Operator
|
|
9
9
|
Scenario: Sequence with skipped sub-expressions
|
10
10
|
Given a grammar with:
|
11
11
|
"""
|
12
|
-
sum <- ~"("
|
12
|
+
sum <- ~"(" @DIGIT+ ~"+" @DIGIT+ ~")"
|
13
13
|
"""
|
14
14
|
When I parse "(23+45)"
|
15
15
|
Then the parse result should be ["23", "45"]
|
@@ -15,7 +15,7 @@ Feature: Symantic Actions
|
|
15
15
|
Scenario: Single token
|
16
16
|
Given a grammar with:
|
17
17
|
"""
|
18
|
-
integer <-
|
18
|
+
integer <- @DIGIT+ {|s| s.to_i }
|
19
19
|
"""
|
20
20
|
When I parse "42"
|
21
21
|
Then the parse result should be 42
|
@@ -24,7 +24,7 @@ Feature: Symantic Actions
|
|
24
24
|
Given a grammar with:
|
25
25
|
"""
|
26
26
|
%whitespace SPACE*
|
27
|
-
product <-
|
27
|
+
product <- @DIGIT+ @DIGIT+ {|a,b| a.to_i * b.to_i }
|
28
28
|
"""
|
29
29
|
When I parse "3 16"
|
30
30
|
Then the parse result should be 48
|
@@ -32,7 +32,7 @@ Feature: Symantic Actions
|
|
32
32
|
Scenario: Sequence with non-capturing expressions
|
33
33
|
Given a grammar with:
|
34
34
|
"""
|
35
|
-
sum <- ~"("
|
35
|
+
sum <- ~"(" @DIGIT+ ~"+" @DIGIT+ ~")" {|a,b| a.to_i + b.to_i }
|
36
36
|
"""
|
37
37
|
When I parse "(23+17)"
|
38
38
|
Then the parse result should be 40
|
@@ -40,7 +40,7 @@ Feature: Symantic Actions
|
|
40
40
|
Scenario: Sequence with labeled expressions
|
41
41
|
Given a grammar with:
|
42
42
|
"""
|
43
|
-
sum <- "(" left
|
43
|
+
sum <- "(" left:@DIGIT+ "+" right:@DIGIT+ ")" { left.to_i + right.to_i }
|
44
44
|
"""
|
45
45
|
When I parse "(17+29)"
|
46
46
|
Then the parse result should be 46
|
@@ -48,7 +48,7 @@ Feature: Symantic Actions
|
|
48
48
|
Scenario: Single token using "_"
|
49
49
|
Given a grammar with:
|
50
50
|
"""
|
51
|
-
integer <-
|
51
|
+
integer <- @DIGIT+ { _.to_i }
|
52
52
|
"""
|
53
53
|
When I parse "23"
|
54
54
|
Then the parse result should be 23
|
@@ -57,7 +57,7 @@ Feature: Symantic Actions
|
|
57
57
|
Given a grammar with:
|
58
58
|
"""
|
59
59
|
%whitespace SPACE*
|
60
|
-
ints <-
|
60
|
+
ints <- @DIGIT+ @DIGIT+ { _.reverse }
|
61
61
|
"""
|
62
62
|
When I parse "3 16"
|
63
63
|
Then the parse result should be ["16", "3"]
|
@@ -66,7 +66,7 @@ Feature: Symantic Actions
|
|
66
66
|
Given a grammar with:
|
67
67
|
"""
|
68
68
|
%whitespace SPACE*
|
69
|
-
ints <-
|
69
|
+
ints <- @DIGIT+ @DIGIT+ {|_| _.to_i }
|
70
70
|
"""
|
71
71
|
When I parse "3 16"
|
72
72
|
Then the parse result should be 3
|
@@ -14,7 +14,7 @@ Feature: Whitespace
|
|
14
14
|
Given a grammar with:
|
15
15
|
"""
|
16
16
|
%whitespace SPACE* {
|
17
|
-
word <-
|
17
|
+
word <- @WORD+
|
18
18
|
}
|
19
19
|
"""
|
20
20
|
When I parse " foo"
|
@@ -24,7 +24,7 @@ Feature: Whitespace
|
|
24
24
|
Given a grammar with:
|
25
25
|
"""
|
26
26
|
%whitespace SPACE*
|
27
|
-
word <-
|
27
|
+
word <- @WORD+
|
28
28
|
"""
|
29
29
|
When I parse " foo"
|
30
30
|
Then the parse result should be "foo"
|
data/lib/rattler/back_end.rb
CHANGED
@@ -13,15 +13,16 @@ module Rattler::BackEnd
|
|
13
13
|
# @author Jason Arhart
|
14
14
|
#
|
15
15
|
class Compiler
|
16
|
-
|
16
|
+
|
17
|
+
include Rattler::Grammar
|
17
18
|
include Rattler::Parsers
|
18
|
-
|
19
|
+
|
19
20
|
# Compile rules or grammar source into a new parser subclass of +base+.
|
20
21
|
#
|
21
22
|
# @overload compile_parser(base, rules)
|
22
23
|
# Compile +rules+ into a new parser subclass of +base+.
|
23
24
|
# @param [Class] base the base class for the new parser class
|
24
|
-
# @param [Rattler::Parser::
|
25
|
+
# @param [Rattler::Parser::RuleSet] rules the rules to compile
|
25
26
|
# @return [Class] a new parser class
|
26
27
|
#
|
27
28
|
# @overload compile_parser(base, rule)
|
@@ -40,33 +41,33 @@ module Rattler::BackEnd
|
|
40
41
|
parser_class = Class.new(base)
|
41
42
|
compile(parser_class, rules_or_grammar)
|
42
43
|
end
|
43
|
-
|
44
|
+
|
44
45
|
# Compile rules or grammar source into match methods in the module +mod+.
|
45
46
|
def self.compile(mod, rules_or_grammar)
|
46
47
|
self.new(mod).compile(rules_or_grammar)
|
47
48
|
end
|
48
|
-
|
49
|
+
|
49
50
|
# Compile +rules+ into match methods in the module +mod+.
|
50
51
|
def self.compile_rules(mod, rules)
|
51
52
|
self.new(mod).compile_rules(rules)
|
52
53
|
end
|
53
|
-
|
54
|
+
|
54
55
|
# Compile grammar +source+ into a match method in the module +mod+.
|
55
56
|
def compile_grammar(mod, source)
|
56
57
|
self.new(mod).compiler_grammar(source)
|
57
58
|
end
|
58
|
-
|
59
|
+
|
59
60
|
# Create a new compiler that compiles rules into match methods in the
|
60
61
|
# given module.
|
61
62
|
def initialize(mod)
|
62
63
|
@mod = mod
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
# Compile the rules or grammar source into match methods in the module.
|
66
67
|
#
|
67
68
|
# @overload compile(rules)
|
68
69
|
# Compile +rules+ into match methods in the module.
|
69
|
-
# @param [Rattler::Parser::
|
70
|
+
# @param [Rattler::Parser::RuleSet] rules the rules to compile
|
70
71
|
# @return [Module] the module
|
71
72
|
#
|
72
73
|
# @overload compile(rule)
|
@@ -81,17 +82,16 @@ module Rattler::BackEnd
|
|
81
82
|
#
|
82
83
|
def compile(_)
|
83
84
|
case _
|
84
|
-
when
|
85
|
-
when Rule then compile_rules(_)
|
85
|
+
when Grammar, RuleSet, Rule then compile_rules(_)
|
86
86
|
else compile_grammar(_.to_s)
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Compile +rules+ into match methods in the module.
|
91
91
|
#
|
92
92
|
# @overload compile_rules(rules)
|
93
93
|
# Compile +rules+ into match methods in the module.
|
94
|
-
# @param [Rattler::Parser::
|
94
|
+
# @param [Rattler::Parser::RuleSet] rules the rules to compile
|
95
95
|
# @return [Module] the module
|
96
96
|
#
|
97
97
|
# @overload compile_rules(rule)
|
@@ -100,10 +100,9 @@ module Rattler::BackEnd
|
|
100
100
|
# @return [Module] the module
|
101
101
|
#
|
102
102
|
def compile_rules(rules)
|
103
|
-
|
104
|
-
compile_model(rules.optimized)
|
103
|
+
compile_model(rules)
|
105
104
|
end
|
106
|
-
|
105
|
+
|
107
106
|
# Compile +grammar+ into match methods in the module.
|
108
107
|
# @param [String] grammar the grammar source to compile
|
109
108
|
# @return [Module] the module
|
@@ -111,19 +110,19 @@ module Rattler::BackEnd
|
|
111
110
|
result = Rattler::Grammar.parse!(source)
|
112
111
|
compile_model(result.rules)
|
113
112
|
end
|
114
|
-
|
113
|
+
|
115
114
|
private
|
116
|
-
|
115
|
+
|
117
116
|
def assert_kind_of(kinds, model) #:nodoc:
|
118
117
|
unless kinds.any? {|kind| model.kind_of?(kind) }
|
119
118
|
raise TypeError, "Expected #{model.inspect} to be a kind of #{klass}", caller
|
120
119
|
end
|
121
120
|
end
|
122
|
-
|
121
|
+
|
123
122
|
def compile_model(model) #:nodoc:
|
124
123
|
@mod.module_eval ParserGenerator.code_for(model)
|
125
124
|
@mod
|
126
125
|
end
|
127
|
-
|
126
|
+
|
128
127
|
end
|
129
128
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd
|
10
|
+
#
|
11
|
+
# The +Optimizer+ transforms parser models into equivalent models that can
|
12
|
+
# result in more efficient parsing code. This is primarily achieved by
|
13
|
+
# converting regular expressions into equivalent Regexp patterns, thus
|
14
|
+
# reducing object instantiation and method dispatch and having StringScanner
|
15
|
+
# do as much of the parsing work as possible.
|
16
|
+
#
|
17
|
+
# @author Jason Arhart
|
18
|
+
#
|
19
|
+
module Optimizer
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def optimizations
|
23
|
+
@optimizations ||=
|
24
|
+
OptimizeChildren >>
|
25
|
+
InlineRegularRules >>
|
26
|
+
SimplifyRedundantRepeat >>
|
27
|
+
RemoveMeaninglessWrapper >>
|
28
|
+
SimplifyTokenMatch >>
|
29
|
+
FlattenSequence >>
|
30
|
+
FlattenChoice >>
|
31
|
+
ReduceRepeatMatch >>
|
32
|
+
JoinPredicateMatch >>
|
33
|
+
JoinPredicateOrMatch >>
|
34
|
+
JoinMatchSequence >>
|
35
|
+
JoinMatchChoice
|
36
|
+
end
|
37
|
+
|
38
|
+
def optimize(model, opts={})
|
39
|
+
case model
|
40
|
+
when ::Rattler::Grammar::Grammar then optimize_grammar model, opts
|
41
|
+
when ::Rattler::Parsers::RuleSet then optimize_rule_set model, opts
|
42
|
+
when ::Rattler::Parsers::Rule then optimize_rule model, default_context(opts)
|
43
|
+
else optimize_expr model, default_context(opts)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def default_context(opts)
|
50
|
+
OptimizationContext[opts.merge :type => :capturing]
|
51
|
+
end
|
52
|
+
|
53
|
+
def optimize_grammar(grammar, opts)
|
54
|
+
grammar.with_rules optimize_rule_set(grammar.rules, opts)
|
55
|
+
end
|
56
|
+
|
57
|
+
def optimize_rule_set(rule_set, opts)
|
58
|
+
context = default_context(opts).with(:rules => rule_set)
|
59
|
+
rule_set = rule_set.map_rules {|_| optimize_rule _, context }
|
60
|
+
context = context.with(:rules => rule_set)
|
61
|
+
rule_set.select_rules {|_| context.relavent? _ }
|
62
|
+
end
|
63
|
+
|
64
|
+
def optimize_rule(rule, context)
|
65
|
+
rule.with_expr optimizations.apply(rule.expr, context)
|
66
|
+
end
|
67
|
+
|
68
|
+
def optimize_expr(expr, context)
|
69
|
+
optimizations.apply rule.expr, context
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
autoload :OptimizationContext, 'rattler/back_end/optimizer/optimization_context'
|
75
|
+
autoload :Optimization, 'rattler/back_end/optimizer/optimization'
|
76
|
+
autoload :OptimizationSequence, 'rattler/back_end/optimizer/optimization_sequence'
|
77
|
+
autoload :OptimizeChildren, 'rattler/back_end/optimizer/optimize_children'
|
78
|
+
autoload :InlineRegularRules, 'rattler/back_end/optimizer/inline_regular_rules'
|
79
|
+
autoload :SimplifyRedundantRepeat, 'rattler/back_end/optimizer/simplify_redundant_repeat'
|
80
|
+
autoload :RemoveMeaninglessWrapper, 'rattler/back_end/optimizer/remove_meaningless_wrapper'
|
81
|
+
autoload :SimplifyTokenMatch, 'rattler/back_end/optimizer/simplify_token_match'
|
82
|
+
autoload :FlattenSequence, 'rattler/back_end/optimizer/flatten_sequence'
|
83
|
+
autoload :FlattenChoice, 'rattler/back_end/optimizer/flatten_choice'
|
84
|
+
autoload :ReduceRepeatMatch, 'rattler/back_end/optimizer/reduce_repeat_match'
|
85
|
+
autoload :JoinPredicateMatch, 'rattler/back_end/optimizer/join_predicate_match'
|
86
|
+
autoload :JoinPredicateBareMatch, 'rattler/back_end/optimizer/join_predicate_bare_match'
|
87
|
+
autoload :JoinPredicateNestedMatch, 'rattler/back_end/optimizer/join_predicate_nested_match'
|
88
|
+
autoload :JoinPredicateOrMatch, 'rattler/back_end/optimizer/join_predicate_or_match'
|
89
|
+
autoload :JoinPredicateOrBareMatch, 'rattler/back_end/optimizer/join_predicate_or_bare_match'
|
90
|
+
autoload :JoinPredicateOrNestedMatch, 'rattler/back_end/optimizer/join_predicate_or_nested_match'
|
91
|
+
autoload :JoinMatchSequence, 'rattler/back_end/optimizer/join_match_sequence'
|
92
|
+
autoload :JoinMatchCapturingSequence, 'rattler/back_end/optimizer/join_match_capturing_sequence'
|
93
|
+
autoload :JoinMatchMatchingSequence, 'rattler/back_end/optimizer/join_match_matching_sequence'
|
94
|
+
autoload :JoinMatchChoice, 'rattler/back_end/optimizer/join_match_choice'
|
95
|
+
autoload :MatchJoining, 'rattler/back_end/optimizer/match_joining'
|
96
|
+
autoload :Flattening, 'rattler/back_end/optimizer/flattening'
|
97
|
+
autoload :CompositeReducing, 'rattler/back_end/optimizer/composite_reducing'
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rattler'
|
2
|
+
|
3
|
+
module Rattler::BackEnd::Optimizer
|
4
|
+
# @private
|
5
|
+
module CompositeReducing #:nodoc:
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def finish_reduce(parser, new_children)
|
10
|
+
if new_children.size == 1
|
11
|
+
new_children[0]
|
12
|
+
else
|
13
|
+
parser.with_children new_children
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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
|
+
# Nested choice expressions can be flattened without affecting how they parse.
|
12
|
+
#
|
13
|
+
# @author Jason Arhart
|
14
|
+
#
|
15
|
+
class FlattenChoice < Optimization
|
16
|
+
include Flattening
|
17
|
+
|
18
|
+
include Rattler::Parsers
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def _applies_to?(parser, context)
|
23
|
+
parser.is_a?(Choice) and super
|
24
|
+
end
|
25
|
+
|
26
|
+
def eligible_child?(child)
|
27
|
+
child.is_a? Choice
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/back_end/optimizer/flatten_sequence.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
require 'rattler'
|
8
|
+
|
9
|
+
module Rattler::BackEnd::Optimizer
|
10
|
+
|
11
|
+
#
|
12
|
+
# Nested sequence expressions can be flattened without affecting how they
|
13
|
+
# match.
|
14
|
+
#
|
15
|
+
# @author Jason Arhart
|
16
|
+
#
|
17
|
+
class FlattenMatchingSequence < Optimization
|
18
|
+
include Flattening
|
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
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def eligible_child?(child)
|
30
|
+
child.is_a? Sequence
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Nested sequence expressions can be flattened without affecting how they
|
36
|
+
# parse if the nested sequence expressions are not multi-capturing.
|
37
|
+
#
|
38
|
+
# @author Jason Arhart
|
39
|
+
#
|
40
|
+
class FlattenCapturingSequence < Optimization
|
41
|
+
include Flattening
|
42
|
+
include Rattler::Parsers
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def _applies_to?(parser, context)
|
47
|
+
context.capturing? and
|
48
|
+
parser.is_a?(Sequence) and
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def eligible_child?(child)
|
53
|
+
child.is_a?(Sequence) and child.capture_count <= 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
FlattenSequence = FlattenMatchingSequence >> FlattenCapturingSequence
|
58
|
+
|
59
|
+
end
|