treetop 0.1.0 → 1.0.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 +3 -0
- data/Rakefile +35 -0
- data/bin/tt +25 -0
- data/lib/treetop.rb +10 -6
- data/lib/treetop/compiler.rb +7 -0
- data/lib/treetop/compiler/grammar_compiler.rb +21 -0
- data/lib/treetop/compiler/lexical_address_space.rb +17 -0
- data/lib/treetop/compiler/load_grammar.rb +7 -0
- data/lib/treetop/compiler/metagrammar.rb +2441 -0
- data/lib/treetop/compiler/metagrammar.treetop +384 -0
- data/lib/treetop/compiler/node_classes.rb +18 -0
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -0
- data/lib/treetop/compiler/node_classes/atomic_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/character_class.rb +10 -0
- data/lib/treetop/compiler/node_classes/choice.rb +31 -0
- data/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
- data/lib/treetop/compiler/node_classes/grammar.rb +28 -0
- data/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
- data/lib/treetop/compiler/node_classes/nonterminal.rb +11 -0
- data/lib/treetop/compiler/node_classes/optional.rb +19 -0
- data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +132 -0
- data/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
- data/lib/treetop/compiler/node_classes/predicate.rb +45 -0
- data/lib/treetop/compiler/node_classes/repetition.rb +56 -0
- data/lib/treetop/compiler/node_classes/sequence.rb +64 -0
- data/lib/treetop/compiler/node_classes/terminal.rb +10 -0
- data/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
- data/lib/treetop/compiler/ruby_builder.rb +109 -0
- data/lib/treetop/ruby_extensions.rb +2 -0
- data/lib/treetop/ruby_extensions/string.rb +19 -0
- data/lib/treetop/runtime.rb +9 -0
- data/lib/treetop/runtime/compiled_parser.rb +66 -0
- data/lib/treetop/runtime/node_cache.rb +27 -0
- data/lib/treetop/runtime/parse_cache.rb +19 -0
- data/lib/treetop/runtime/parse_failure.rb +32 -0
- data/lib/treetop/runtime/parse_result.rb +30 -0
- data/lib/treetop/runtime/syntax_node.rb +53 -0
- data/lib/treetop/runtime/terminal_parse_failure.rb +33 -0
- data/lib/treetop/runtime/terminal_syntax_node.rb +12 -0
- data/test/compilation_target/target.rb +143 -0
- data/test/compilation_target/target.treetop +15 -0
- data/test/compilation_target/target_test.rb +56 -0
- data/test/compiler/and_predicate_test.rb +33 -0
- data/test/compiler/anything_symbol_test.rb +24 -0
- data/test/compiler/character_class_test.rb +45 -0
- data/test/compiler/choice_test.rb +49 -0
- data/test/compiler/circular_compilation_test.rb +20 -0
- data/test/compiler/failure_propagation_functional_test.rb +20 -0
- data/test/compiler/grammar_compiler_test.rb +58 -0
- data/test/compiler/grammar_test.rb +33 -0
- data/test/compiler/nonterminal_symbol_test.rb +15 -0
- data/test/compiler/not_predicate_test.rb +35 -0
- data/test/compiler/one_or_more_test.rb +30 -0
- data/test/compiler/optional_test.rb +32 -0
- data/test/compiler/parsing_rule_test.rb +30 -0
- data/test/compiler/sequence_test.rb +68 -0
- data/test/compiler/terminal_symbol_test.rb +35 -0
- data/test/compiler/test_grammar.treetop +7 -0
- data/test/compiler/zero_or_more_test.rb +51 -0
- data/test/composition/a.treetop +11 -0
- data/test/composition/b.treetop +11 -0
- data/test/composition/c.treetop +10 -0
- data/test/composition/d.treetop +10 -0
- data/test/composition/grammar_composition_test.rb +23 -0
- data/test/parser/syntax_node_test.rb +53 -0
- data/test/parser/terminal_parse_failure_test.rb +22 -0
- data/test/ruby_extensions/string_test.rb +33 -0
- data/test/screw/Rakefile +16 -0
- data/test/screw/unit.rb +37 -0
- data/test/screw/unit/assertion_failed_error.rb +14 -0
- data/test/screw/unit/assertions.rb +615 -0
- data/test/screw/unit/auto_runner.rb +227 -0
- data/test/screw/unit/collector.rb +45 -0
- data/test/screw/unit/collector/dir.rb +107 -0
- data/test/screw/unit/collector/objectspace.rb +28 -0
- data/test/screw/unit/error.rb +48 -0
- data/test/screw/unit/failure.rb +45 -0
- data/test/screw/unit/sugar.rb +25 -0
- data/test/screw/unit/test_case.rb +176 -0
- data/test/screw/unit/test_result.rb +73 -0
- data/test/screw/unit/test_suite.rb +70 -0
- data/test/screw/unit/ui.rb +4 -0
- data/test/screw/unit/ui/console/test_runner.rb +118 -0
- data/test/screw/unit/ui/fox/test_runner.rb +268 -0
- data/test/screw/unit/ui/gtk/test_runner.rb +416 -0
- data/test/screw/unit/ui/gtk2/testrunner.rb +465 -0
- data/test/screw/unit/ui/test_runner_mediator.rb +58 -0
- data/test/screw/unit/ui/test_runner_utilities.rb +46 -0
- data/test/screw/unit/ui/tk/test_runner.rb +260 -0
- data/test/screw/unit/util.rb +4 -0
- data/test/screw/unit/util/backtrace_filter.rb +40 -0
- data/test/screw/unit/util/observable.rb +82 -0
- data/test/screw/unit/util/proc_wrapper.rb +48 -0
- data/test/test_helper.rb +89 -0
- metadata +127 -69
- data/lib/treetop/api.rb +0 -3
- data/lib/treetop/api/load_grammar.rb +0 -16
- data/lib/treetop/api/malformed_grammar_exception.rb +0 -9
- data/lib/treetop/grammar.rb +0 -7
- data/lib/treetop/grammar/grammar.rb +0 -48
- data/lib/treetop/grammar/grammar_builder.rb +0 -35
- data/lib/treetop/grammar/parsing_expression_builder.rb +0 -5
- data/lib/treetop/grammar/parsing_expression_builder_helper.rb +0 -121
- data/lib/treetop/grammar/parsing_expressions.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/and_predicate.rb +0 -17
- data/lib/treetop/grammar/parsing_expressions/anything_symbol.rb +0 -20
- data/lib/treetop/grammar/parsing_expressions/character_class.rb +0 -24
- data/lib/treetop/grammar/parsing_expressions/node_instantiating_parsing_expression.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/node_propagating_parsing_expression.rb +0 -4
- data/lib/treetop/grammar/parsing_expressions/nonterminal_symbol.rb +0 -42
- data/lib/treetop/grammar/parsing_expressions/not_predicate.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/one_or_more.rb +0 -12
- data/lib/treetop/grammar/parsing_expressions/optional.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/ordered_choice.rb +0 -27
- data/lib/treetop/grammar/parsing_expressions/parsing_expression.rb +0 -36
- data/lib/treetop/grammar/parsing_expressions/predicate.rb +0 -25
- data/lib/treetop/grammar/parsing_expressions/repeating_parsing_expression.rb +0 -29
- data/lib/treetop/grammar/parsing_expressions/sequence.rb +0 -41
- data/lib/treetop/grammar/parsing_expressions/terminal_parsing_expression.rb +0 -11
- data/lib/treetop/grammar/parsing_expressions/terminal_symbol.rb +0 -31
- data/lib/treetop/grammar/parsing_expressions/zero_or_more.rb +0 -11
- data/lib/treetop/grammar/parsing_rule.rb +0 -10
- data/lib/treetop/metagrammar.rb +0 -2
- data/lib/treetop/metagrammar/metagrammar.rb +0 -14
- data/lib/treetop/metagrammar/metagrammar.treetop +0 -320
- data/lib/treetop/parser.rb +0 -11
- data/lib/treetop/parser/node_cache.rb +0 -25
- data/lib/treetop/parser/parse_cache.rb +0 -17
- data/lib/treetop/parser/parse_failure.rb +0 -22
- data/lib/treetop/parser/parse_result.rb +0 -26
- data/lib/treetop/parser/parser.rb +0 -24
- data/lib/treetop/parser/sequence_syntax_node.rb +0 -14
- data/lib/treetop/parser/syntax_node.rb +0 -31
- data/lib/treetop/parser/terminal_parse_failure.rb +0 -18
- data/lib/treetop/parser/terminal_syntax_node.rb +0 -7
- data/lib/treetop/protometagrammar.rb +0 -16
- data/lib/treetop/protometagrammar/anything_symbol_expression_builder.rb +0 -13
- data/lib/treetop/protometagrammar/block_expression_builder.rb +0 -17
- data/lib/treetop/protometagrammar/character_class_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/grammar_expression_builder.rb +0 -38
- data/lib/treetop/protometagrammar/nonterminal_symbol_expression_builder.rb +0 -45
- data/lib/treetop/protometagrammar/ordered_choice_expression_builder.rb +0 -21
- data/lib/treetop/protometagrammar/parsing_rule_expression_builder.rb +0 -23
- data/lib/treetop/protometagrammar/parsing_rule_sequence_expression_builder.rb +0 -14
- data/lib/treetop/protometagrammar/prefix_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/primary_expression_builder.rb +0 -71
- data/lib/treetop/protometagrammar/protometagrammar.rb +0 -25
- data/lib/treetop/protometagrammar/sequence_expression_builder.rb +0 -37
- data/lib/treetop/protometagrammar/suffix_expression_builder.rb +0 -33
- data/lib/treetop/protometagrammar/terminal_symbol_expression_builder.rb +0 -52
- data/lib/treetop/protometagrammar/trailing_block_expression_builder.rb +0 -30
- data/lib/treetop/ruby_extension.rb +0 -11
@@ -0,0 +1,24 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class DeclarationSequence < Runtime::SyntaxNode
|
4
|
+
|
5
|
+
def compile(builder)
|
6
|
+
unless rules.empty?
|
7
|
+
builder.method_declaration("root") do
|
8
|
+
builder << rules.first.method_name
|
9
|
+
end
|
10
|
+
builder.newline
|
11
|
+
end
|
12
|
+
|
13
|
+
declarations.each do |declaration|
|
14
|
+
declaration.compile(builder)
|
15
|
+
builder.newline
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def rules
|
20
|
+
declarations.select { |declaration| declaration.instance_of?(ParsingRule) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class Grammar < Runtime::SyntaxNode
|
4
|
+
def compile
|
5
|
+
builder = RubyBuilder.new
|
6
|
+
|
7
|
+
builder.module_declaration "#{grammar_name.text_value}" do
|
8
|
+
builder.in(indent_level) # account for initial indentation of grammar declaration
|
9
|
+
builder << "include ::Treetop::Runtime"
|
10
|
+
builder.newline
|
11
|
+
declaration_sequence.compile(builder)
|
12
|
+
end
|
13
|
+
builder.newline
|
14
|
+
builder.class_declaration "#{parser_name} < ::Treetop::Runtime::CompiledParser" do
|
15
|
+
builder << "include #{grammar_name.text_value}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def indent_level
|
20
|
+
input.column_of(interval.begin) - 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def parser_name
|
24
|
+
grammar_name.text_value + 'Parser'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
module InlineModuleMixin
|
4
|
+
attr_reader :module_name
|
5
|
+
|
6
|
+
def compile(index, rule, builder)
|
7
|
+
@module_name = "#{rule.name.camelize}#{index}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class InlineModule < Runtime::SyntaxNode
|
12
|
+
|
13
|
+
include InlineModuleMixin
|
14
|
+
|
15
|
+
def compile(index, rule, builder)
|
16
|
+
super
|
17
|
+
builder.module_declaration(module_name) do
|
18
|
+
builder << ruby_code.gsub(/\A\n/, '').rstrip
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def ruby_code
|
23
|
+
elements[1].text_value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class Optional < ParsingExpression
|
4
|
+
def compile(address, builder, parent_expression)
|
5
|
+
super
|
6
|
+
use_vars :result
|
7
|
+
obtain_new_subexpression_address
|
8
|
+
parent_expression.atomic.compile(subexpression_address, builder)
|
9
|
+
|
10
|
+
builder.if__ subexpression_success? do
|
11
|
+
assign_result subexpression_result_var
|
12
|
+
end
|
13
|
+
builder.else_ do
|
14
|
+
assign_result epsilon_node
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class ParsingExpression < Runtime::SyntaxNode
|
4
|
+
attr_reader :address, :builder, :subexpression_address, :var_symbols, :parent_expression
|
5
|
+
|
6
|
+
def compile(address, builder, parent_expression)
|
7
|
+
@address = address
|
8
|
+
@builder = builder
|
9
|
+
@parent_expression = parent_expression
|
10
|
+
end
|
11
|
+
|
12
|
+
def node_class
|
13
|
+
parent_expression && parent_expression.node_class || 'SyntaxNode'
|
14
|
+
end
|
15
|
+
|
16
|
+
def inline_module_name
|
17
|
+
return nil unless parent_expression
|
18
|
+
parent_expression.inline_module_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def optional_arg(arg)
|
22
|
+
if arg
|
23
|
+
", #{arg}"
|
24
|
+
else
|
25
|
+
''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def use_vars(*var_symbols)
|
30
|
+
@var_symbols = var_symbols
|
31
|
+
builder << var_initialization
|
32
|
+
end
|
33
|
+
|
34
|
+
def result_var
|
35
|
+
var(:result)
|
36
|
+
end
|
37
|
+
|
38
|
+
def accumulator_var
|
39
|
+
var(:accumulator)
|
40
|
+
end
|
41
|
+
|
42
|
+
def nested_results_var
|
43
|
+
var(:nested_results)
|
44
|
+
end
|
45
|
+
|
46
|
+
def start_index_var
|
47
|
+
var(:start_index)
|
48
|
+
end
|
49
|
+
|
50
|
+
def subexpression_result_var
|
51
|
+
"r#{subexpression_address}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def subexpression_success?
|
55
|
+
subexpression_result_var + ".success?"
|
56
|
+
end
|
57
|
+
|
58
|
+
def obtain_new_subexpression_address
|
59
|
+
@subexpression_address = builder.next_address
|
60
|
+
end
|
61
|
+
|
62
|
+
def accumulate_nested_result
|
63
|
+
builder.accumulate nested_results_var, subexpression_result_var
|
64
|
+
end
|
65
|
+
|
66
|
+
def accumulate_subexpression_result
|
67
|
+
builder.accumulate accumulator_var, subexpression_result_var
|
68
|
+
end
|
69
|
+
|
70
|
+
def assign_result(value_ruby)
|
71
|
+
builder.assign result_var, value_ruby
|
72
|
+
end
|
73
|
+
|
74
|
+
def reset_index
|
75
|
+
builder.assign 'self.index', start_index_var
|
76
|
+
end
|
77
|
+
|
78
|
+
def epsilon_node
|
79
|
+
"SyntaxNode.new(input, index...index, #{subexpression_result_var}.nested_failures)"
|
80
|
+
end
|
81
|
+
|
82
|
+
def assign_failure(start_index_var, nested_results_var)
|
83
|
+
assign_result("ParseFailure.new(input, #{start_index_var}, #{nested_results_var})")
|
84
|
+
end
|
85
|
+
|
86
|
+
def var_initialization
|
87
|
+
left, right = [], []
|
88
|
+
var_symbols.each do |symbol|
|
89
|
+
if init_value(symbol)
|
90
|
+
left << var(symbol)
|
91
|
+
right << init_value(symbol)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
if left.empty?
|
95
|
+
""
|
96
|
+
else
|
97
|
+
left.join(', ') + ' = ' + right.join(', ')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def var(var_symbol)
|
102
|
+
case var_symbol
|
103
|
+
when :result then "r#{address}"
|
104
|
+
when :accumulator then "s#{address}"
|
105
|
+
when :nested_results then "nr#{address}"
|
106
|
+
when :start_index then "i#{address}"
|
107
|
+
else raise "Unknown var symbol #{var_symbol}."
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def init_value(var_symbol)
|
112
|
+
case var_symbol
|
113
|
+
when :accumulator, :nested_results then '[]'
|
114
|
+
when :start_index then 'index'
|
115
|
+
else nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def begin_comment(expression)
|
120
|
+
#builder << "# begin #{on_one_line(expression)}"
|
121
|
+
end
|
122
|
+
|
123
|
+
def end_comment(expression)
|
124
|
+
#builder << "# end #{on_one_line(expression)}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def on_one_line(expression)
|
128
|
+
expression.text_value.tr("\n", ' ')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class ParsingRule < Runtime::SyntaxNode
|
4
|
+
|
5
|
+
def compile(builder)
|
6
|
+
compile_inline_module_declarations(builder)
|
7
|
+
generate_method_definition(builder)
|
8
|
+
end
|
9
|
+
|
10
|
+
def compile_inline_module_declarations(builder)
|
11
|
+
parsing_expression.inline_modules.each_with_index do |inline_module, i|
|
12
|
+
inline_module.compile(i, self, builder)
|
13
|
+
builder.newline
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_method_definition(builder)
|
18
|
+
builder.reset_addresses
|
19
|
+
expression_address = builder.next_address
|
20
|
+
result_var = "r#{expression_address}"
|
21
|
+
|
22
|
+
builder.method_declaration(method_name) do
|
23
|
+
builder.assign 'start_index', 'index'
|
24
|
+
generate_cache_lookup(builder)
|
25
|
+
builder.newline
|
26
|
+
parsing_expression.compile(expression_address, builder)
|
27
|
+
builder.newline
|
28
|
+
generate_cache_storage(builder, result_var)
|
29
|
+
builder.newline
|
30
|
+
builder << "return #{result_var}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_cache_lookup(builder)
|
35
|
+
builder.assign 'cached', "node_cache[:#{name}][index]"
|
36
|
+
builder.if_ 'cached' do
|
37
|
+
builder << '@index = cached.interval.end'
|
38
|
+
builder << 'return cached'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def generate_cache_storage(builder, result_var)
|
43
|
+
builder.assign "node_cache[:#{name}][start_index]", result_var
|
44
|
+
end
|
45
|
+
|
46
|
+
def method_name
|
47
|
+
"_nt_#{name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def name
|
51
|
+
nonterminal.text_value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class Predicate < ParsingExpression
|
4
|
+
def compile(address, builder, parent_expression)
|
5
|
+
super
|
6
|
+
begin_comment(parent_expression)
|
7
|
+
use_vars :result, :start_index
|
8
|
+
obtain_new_subexpression_address
|
9
|
+
parent_expression.predicated_expression.compile(subexpression_address, builder)
|
10
|
+
builder.if__(subexpression_success?) { when_success }
|
11
|
+
builder.else_ { when_failure }
|
12
|
+
end_comment(parent_expression)
|
13
|
+
end
|
14
|
+
|
15
|
+
def assign_failure
|
16
|
+
super(start_index_var, "#{subexpression_result_var}.nested_failures")
|
17
|
+
end
|
18
|
+
|
19
|
+
def assign_success
|
20
|
+
reset_index
|
21
|
+
assign_result epsilon_node
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class AndPredicate < Predicate
|
26
|
+
def when_success
|
27
|
+
assign_success
|
28
|
+
end
|
29
|
+
|
30
|
+
def when_failure
|
31
|
+
assign_failure
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class NotPredicate < Predicate
|
36
|
+
def when_success
|
37
|
+
assign_failure
|
38
|
+
end
|
39
|
+
|
40
|
+
def when_failure
|
41
|
+
assign_success
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class Repetition < ParsingExpression
|
4
|
+
def compile(address, builder, parent_expression)
|
5
|
+
super
|
6
|
+
repeated_expression = parent_expression.atomic
|
7
|
+
begin_comment(parent_expression)
|
8
|
+
use_vars :result, :accumulator, :nested_results, :start_index
|
9
|
+
|
10
|
+
builder.loop do
|
11
|
+
obtain_new_subexpression_address
|
12
|
+
repeated_expression.compile(subexpression_address, builder)
|
13
|
+
accumulate_nested_result
|
14
|
+
builder.if__ subexpression_success? do
|
15
|
+
accumulate_subexpression_result
|
16
|
+
end
|
17
|
+
builder.else_ do
|
18
|
+
builder.break
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def inline_module_name
|
24
|
+
parent_expression.inline_module_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def assign_and_extend_result
|
28
|
+
assign_result "#{node_class}.new(input, #{start_index_var}...index, #{accumulator_var}, #{nested_results_var})"
|
29
|
+
builder << "#{result_var}.extend(#{inline_module_name})" if inline_module_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
class ZeroOrMore < Repetition
|
35
|
+
def compile(address, builder, parent_expression)
|
36
|
+
super
|
37
|
+
assign_and_extend_result
|
38
|
+
end_comment(parent_expression)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class OneOrMore < Repetition
|
43
|
+
def compile(address, builder, parent_expression)
|
44
|
+
super
|
45
|
+
builder.if__ "#{accumulator_var}.empty?" do
|
46
|
+
reset_index
|
47
|
+
assign_failure start_index_var, nested_results_var
|
48
|
+
end
|
49
|
+
builder.else_ do
|
50
|
+
assign_and_extend_result
|
51
|
+
end
|
52
|
+
end_comment(parent_expression)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Treetop
|
2
|
+
module Compiler
|
3
|
+
class Sequence < ParsingExpression
|
4
|
+
def compile(address, builder, parent_expression = nil)
|
5
|
+
super
|
6
|
+
begin_comment(self)
|
7
|
+
use_vars :result, :start_index, :accumulator, :nested_results
|
8
|
+
compile_sequence_elements(sequence_elements)
|
9
|
+
builder.if__ "#{accumulator_var}.last.success?" do
|
10
|
+
assign_result "(#{node_class_declarations.node_class}).new(input, #{start_index_var}...index, #{accumulator_var})"
|
11
|
+
builder << "#{result_var}.extend(#{sequence_element_accessor_module_name})" if sequence_element_accessor_module_name
|
12
|
+
builder << "#{result_var}.extend(#{inline_module_name})" if inline_module_name
|
13
|
+
end
|
14
|
+
builder.else_ do
|
15
|
+
reset_index
|
16
|
+
assign_failure start_index_var, accumulator_var
|
17
|
+
end
|
18
|
+
end_comment(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def compile_sequence_elements(elements)
|
22
|
+
obtain_new_subexpression_address
|
23
|
+
elements.first.compile(subexpression_address, builder)
|
24
|
+
accumulate_subexpression_result
|
25
|
+
if elements.size > 1
|
26
|
+
builder.if_ subexpression_success? do
|
27
|
+
compile_sequence_elements(elements[1..-1])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def sequence_element_accessor_module
|
33
|
+
@sequence_element_accessor_module ||= SequenceElementAccessorModule.new(sequence_elements)
|
34
|
+
end
|
35
|
+
|
36
|
+
def sequence_element_accessor_module_name
|
37
|
+
sequence_element_accessor_module.module_name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class SequenceElementAccessorModule
|
42
|
+
include InlineModuleMixin
|
43
|
+
attr_reader :sequence_elements
|
44
|
+
|
45
|
+
def initialize(sequence_elements)
|
46
|
+
@sequence_elements = sequence_elements
|
47
|
+
end
|
48
|
+
|
49
|
+
def compile(index, rule, builder)
|
50
|
+
super
|
51
|
+
builder.module_declaration(module_name) do
|
52
|
+
sequence_elements.each_with_index do |element, index|
|
53
|
+
if element.label_name
|
54
|
+
builder.method_declaration(element.label_name) do
|
55
|
+
builder << "elements[#{index}]"
|
56
|
+
end
|
57
|
+
builder.newline unless index == sequence_elements.size - 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|