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
@@ -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,
|
20
|
+
def gen_dispatch_action_nested(repeat, code, scope={})
|
21
21
|
atomic_block do
|
22
|
-
gen_dispatch_action_top_level repeat,
|
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,
|
27
|
-
gen_loop repeat
|
28
|
-
gen_result
|
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,
|
33
|
-
atomic_block { gen_direct_action_top_level repeat,
|
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,
|
37
|
-
gen_loop repeat
|
38
|
-
gen_result
|
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
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
58
|
-
|
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
|
-
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def gen_rule_hook(rule, hook_name)
|
63
40
|
(@g << "# @private").newline
|
64
|
-
@g.block(
|
65
|
-
|
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
|
46
|
+
|
47
|
+
def gen_rule_method(rule, method_name)
|
69
48
|
(@g << "# @private").newline
|
70
|
-
@g.block("def
|
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
|
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(' &&') {
|
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
|
-
|
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,
|
68
|
+
def gen_dispatch_action_nested(sequence, code, scope={})
|
67
69
|
atomic_block do
|
68
|
-
gen_dispatch_action_top_level sequence,
|
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,
|
73
|
-
gen_action_code(sequence) do |
|
74
|
-
|
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,
|
80
|
-
atomic_block { gen_direct_action_top_level sequence,
|
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,
|
84
|
-
gen_action_code(sequence) do |
|
85
|
-
|
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(' &&') {
|
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(' &&') {
|
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
|
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(
|
171
|
+
@g << yield(scope)
|
164
172
|
end
|
165
173
|
end
|
166
174
|
|