rattler 0.2.2 → 0.3.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 +83 -64
- data/features/grammar/comments.feature +24 -0
- data/features/grammar/list_matching.feature +41 -0
- data/features/grammar/symantic_action.feature +30 -12
- data/lib/rattler/back_end/parser_generator/assert_generator.rb +27 -27
- data/lib/rattler/back_end/parser_generator/choice_generator.rb +29 -29
- data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +17 -17
- data/lib/rattler/back_end/parser_generator/disallow_generator.rb +27 -27
- data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +17 -17
- data/lib/rattler/back_end/parser_generator/expr_generator.rb +129 -40
- data/lib/rattler/back_end/parser_generator/label_generator.rb +15 -15
- data/lib/rattler/back_end/parser_generator/list1_generator.rb +61 -0
- data/lib/rattler/back_end/parser_generator/list_generating.rb +71 -0
- data/lib/rattler/back_end/parser_generator/list_generator.rb +57 -0
- data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +14 -15
- data/lib/rattler/back_end/parser_generator/optional_generator.rb +24 -24
- data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +9 -9
- data/lib/rattler/back_end/parser_generator/repeat_generating.rb +16 -16
- data/lib/rattler/back_end/parser_generator/sequence_generator.rb +40 -40
- data/lib/rattler/back_end/parser_generator/skip_generator.rb +18 -18
- data/lib/rattler/back_end/parser_generator/skip_propogating.rb +5 -5
- data/lib/rattler/back_end/parser_generator/sub_generating.rb +128 -0
- data/lib/rattler/back_end/parser_generator/token_generator.rb +15 -15
- data/lib/rattler/back_end/parser_generator/token_propogating.rb +1 -1
- data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +12 -13
- data/lib/rattler/back_end/parser_generator.rb +10 -7
- data/lib/rattler/grammar/grammar_parser.rb +16 -21
- data/lib/rattler/grammar/metagrammar.rb +1039 -1035
- data/lib/rattler/grammar/rattler.rtlr +28 -28
- data/lib/rattler/parsers/action_code.rb +20 -9
- data/lib/rattler/parsers/fail.rb +7 -1
- data/lib/rattler/parsers/list.rb +57 -0
- data/lib/rattler/parsers/list1.rb +58 -0
- data/lib/rattler/parsers/parser_dsl.rb +60 -38
- data/lib/rattler/parsers.rb +5 -3
- data/lib/rattler/runtime/extended_packrat_parser.rb +88 -20
- data/lib/rattler/runtime/packrat_parser.rb +21 -14
- data/lib/rattler/runtime/parser.rb +74 -18
- data/lib/rattler/runtime/recursive_descent_parser.rb +15 -46
- data/spec/rattler/back_end/compiler_spec.rb +173 -107
- data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +304 -0
- data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +288 -0
- data/spec/rattler/grammar/grammar_parser_spec.rb +65 -76
- data/spec/rattler/parsers/action_code_spec.rb +84 -34
- data/spec/rattler/parsers/direct_action_spec.rb +56 -34
- data/spec/rattler/parsers/fail_spec.rb +20 -0
- data/spec/rattler/parsers/list1_spec.rb +82 -0
- data/spec/rattler/parsers/list_spec.rb +82 -0
- data/spec/rattler/parsers/parser_dsl_spec.rb +48 -19
- data/spec/rattler/runtime/extended_packrat_parser_spec.rb +0 -1
- metadata +92 -173
- data/bin/rtlr.bat +0 -3
- data/lib/rattler/back_end/parser_generator/generator_helper.rb +0 -130
- data/lib/rattler/back_end/parser_generator/generators.rb +0 -86
- data/lib/rattler/back_end/parser_generator/nested_generators.rb +0 -15
- data/lib/rattler/back_end/parser_generator/top_level_generators.rb +0 -15
@@ -1,94 +1,94 @@
|
|
1
1
|
require 'rattler/back_end/parser_generator'
|
2
2
|
|
3
3
|
module Rattler::BackEnd::ParserGenerator
|
4
|
-
|
4
|
+
|
5
5
|
# @private
|
6
6
|
class DisallowGenerator < ExprGenerator #:nodoc:
|
7
|
-
|
7
|
+
|
8
8
|
def gen_basic(disallow)
|
9
|
-
generate disallow.child, :
|
9
|
+
generate disallow.child, :disallow
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def gen_assert(disallow)
|
13
13
|
@g << 'false'
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def gen_disallow(disallow)
|
17
17
|
gen_basic disallow
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def gen_skip_nested(disallow)
|
21
21
|
gen_basic_nested disallow
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def gen_skip_top_level(disallow)
|
25
25
|
gen_basic_top_level disallow
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def gen_dispatch_action_nested(disallow, target, method_name)
|
29
29
|
atomic_block { gen_dispatch_action_top_level disallow, target, method_name }
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def gen_dispatch_action_top_level(disallow, target, method_name)
|
33
33
|
gen_action disallow,
|
34
34
|
dispatch_action_result(target, method_name, :array_expr => '[]')
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def gen_direct_action_nested(disallow, code)
|
38
38
|
atomic_block { gen_direct_action_top_level disallow, code }
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def gen_direct_action_top_level(disallow, code)
|
42
42
|
gen_action disallow, direct_action_result(code)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def gen_token_nested(disallow)
|
46
46
|
atomic_block { gen_token_top_level disallow }
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def gen_token_top_level(disallow)
|
50
50
|
gen_action disallow, "''"
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def gen_intermediate(disallow)
|
54
|
-
generate disallow.child, :
|
54
|
+
generate disallow.child, :intermediate_disallow
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def gen_intermediate_disallow(disallow)
|
58
58
|
gen_intermediate disallow
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
def gen_intermediate_skip(disallow)
|
62
62
|
gen_intermediate disallow
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
private
|
66
|
-
|
66
|
+
|
67
67
|
def gen_action(disallow, result_code)
|
68
68
|
gen_intermediate disallow
|
69
69
|
(@g << ' &&').newline << result_code
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
# @private
|
75
75
|
class NestedDisallowGenerator < DisallowGenerator #:nodoc:
|
76
76
|
include Nested
|
77
|
-
include
|
77
|
+
include NestedSubGenerating
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def DisallowGenerator.nested(*args)
|
81
81
|
NestedDisallowGenerator.new(*args)
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
# @private
|
85
85
|
class TopLevelDisallowGenerator < DisallowGenerator #:nodoc:
|
86
86
|
include TopLevel
|
87
|
-
include
|
87
|
+
include TopLevelSubGenerating
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
def DisallowGenerator.top_level(*args)
|
91
91
|
TopLevelDisallowGenerator.new(*args)
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
end
|
@@ -1,61 +1,61 @@
|
|
1
1
|
require 'rattler/back_end/parser_generator'
|
2
2
|
|
3
3
|
module Rattler::BackEnd::ParserGenerator
|
4
|
-
|
4
|
+
|
5
5
|
# @private
|
6
6
|
class DispatchActionGenerator < ExprGenerator #:nodoc:
|
7
7
|
include PredicatePropogating
|
8
8
|
include TokenPropogating
|
9
9
|
include SkipPropogating
|
10
|
-
|
10
|
+
|
11
11
|
def gen_basic_nested(action)
|
12
|
-
generate action.child, :
|
12
|
+
generate action.child, :dispatch_action_nested,
|
13
13
|
action.target, action.method_name
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def gen_basic_top_level(action)
|
17
|
-
generate action.child, :
|
17
|
+
generate action.child, :dispatch_action_top_level,
|
18
18
|
action.target, action.method_name
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def gen_dispatch_action_nested(inner, target, method_name)
|
22
22
|
atomic_block { gen_dispatch_action_top_level inner, target, method_name }
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def gen_dispatch_action_top_level(inner, target, method_name)
|
26
26
|
@g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
|
27
27
|
(@g << ' &&').newline << dispatch_action_result(target, method_name)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def gen_direct_action_nested(inner, code)
|
31
31
|
atomic_block { gen_direct_action_top_level inner, code }
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def gen_direct_action_top_level(inner, code)
|
35
35
|
@g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
|
36
36
|
(@g << ' &&').newline << direct_action_result(code)
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
# @private
|
42
42
|
class NestedDispatchActionGenerator < DispatchActionGenerator #:nodoc:
|
43
43
|
include Nested
|
44
|
-
include
|
44
|
+
include NestedSubGenerating
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def DispatchActionGenerator.nested(*args)
|
48
48
|
NestedDispatchActionGenerator.new(*args)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
# @private
|
52
52
|
class TopLevelDispatchActionGenerator < DispatchActionGenerator #:nodoc:
|
53
53
|
include TopLevel
|
54
|
-
include
|
54
|
+
include TopLevelSubGenerating
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def DispatchActionGenerator.top_level(*args)
|
58
58
|
TopLevelDispatchActionGenerator.new(*args)
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
end
|
@@ -1,60 +1,149 @@
|
|
1
1
|
require 'rattler/back_end/parser_generator'
|
2
2
|
|
3
3
|
module Rattler::BackEnd::ParserGenerator
|
4
|
-
|
4
|
+
|
5
5
|
# @private
|
6
6
|
class ExprGenerator #:nodoc:
|
7
|
-
include GeneratorHelper
|
8
|
-
|
7
|
+
# include GeneratorHelper
|
8
|
+
|
9
9
|
include Rattler::Parsers
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(g, choice_level=nil, sequence_level=nil, repeat_level=nil)
|
12
12
|
@g = g
|
13
13
|
@choice_level = choice_level
|
14
14
|
@sequence_level = sequence_level
|
15
15
|
@repeat_level = repeat_level
|
16
16
|
end
|
17
|
-
|
18
|
-
def
|
19
|
-
|
20
|
-
when Eof then gen_eof
|
21
|
-
else generator(parser).send(gen_method, parser, *args)
|
22
|
-
end
|
17
|
+
|
18
|
+
def gen_basic_nested(parser)
|
19
|
+
gen_basic parser
|
23
20
|
end
|
24
|
-
|
25
|
-
def
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
21
|
+
|
22
|
+
def gen_basic_top_level(parser)
|
23
|
+
gen_basic parser
|
24
|
+
end
|
25
|
+
|
26
|
+
def gen_assert_nested(parser)
|
27
|
+
gen_assert parser
|
28
|
+
end
|
29
|
+
|
30
|
+
def gen_assert_top_level(parser)
|
31
|
+
gen_assert parser
|
32
|
+
end
|
33
|
+
|
34
|
+
def gen_disallow_nested(parser)
|
35
|
+
gen_disallow parser
|
36
|
+
end
|
37
|
+
|
38
|
+
def gen_disallow_top_level(parser)
|
39
|
+
gen_disallow parser
|
40
|
+
end
|
41
|
+
|
42
|
+
def gen_dispatch_action_nested(parser, target, method_name)
|
43
|
+
gen_dispatch_action parser, target, method_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def gen_dispatch_action_top_level(parser, target, method_name)
|
47
|
+
gen_dispatch_action parser, target, method_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def gen_direct_action_nested(parser, action)
|
51
|
+
gen_direct_action parser, action
|
52
|
+
end
|
53
|
+
|
54
|
+
def gen_direct_action_top_level(parser, action)
|
55
|
+
gen_direct_action parser, action
|
56
|
+
end
|
57
|
+
|
58
|
+
def gen_token_nested(parser)
|
59
|
+
atomic_block { gen_token_top_level parser }
|
60
|
+
end
|
61
|
+
|
62
|
+
def gen_token_top_level(parser)
|
63
|
+
(@g << "tp = @scanner.pos").newline
|
64
|
+
gen_intermediate_skip parser
|
65
|
+
(@g << ' &&').newline
|
66
|
+
@g << "@scanner.string[tp...(@scanner.pos)]"
|
67
|
+
end
|
68
|
+
|
69
|
+
def gen_skip_nested(parser)
|
70
|
+
gen_skip parser
|
71
|
+
end
|
72
|
+
|
73
|
+
def gen_skip_top_level(parser)
|
74
|
+
gen_skip parser
|
49
75
|
end
|
50
|
-
|
76
|
+
|
77
|
+
def gen_intermediate(parser)
|
78
|
+
gen_basic_nested parser
|
79
|
+
end
|
80
|
+
|
81
|
+
def gen_intermediate_assert(parser)
|
82
|
+
gen_assert_nested parser
|
83
|
+
end
|
84
|
+
|
85
|
+
def gen_intermediate_disallow(parser)
|
86
|
+
gen_disallow_nested parser
|
87
|
+
end
|
88
|
+
|
89
|
+
def gen_intermediate_skip(parser)
|
90
|
+
gen_skip_nested parser
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
51
95
|
attr_reader :choice_level, :sequence_level, :repeat_level
|
52
|
-
|
96
|
+
|
97
|
+
def atomic_expr
|
98
|
+
@g.surround('(', ')') { yield }
|
99
|
+
end
|
100
|
+
|
101
|
+
def atomic_block
|
102
|
+
@g.block('begin') { yield }
|
103
|
+
end
|
104
|
+
|
105
|
+
def result_name
|
106
|
+
'r'
|
107
|
+
end
|
108
|
+
|
109
|
+
def saved_pos_name
|
110
|
+
"p#{sequence_level}"
|
111
|
+
end
|
112
|
+
|
113
|
+
def dispatch_action_result(target, method_name, options = {})
|
114
|
+
args = [options[:array_expr] || "[#{result_name}]"]
|
115
|
+
labeled = options[:labeled]
|
116
|
+
if labeled and not labeled.empty?
|
117
|
+
if labeled.respond_to?(:to_hash)
|
118
|
+
labeled = '{' + labeled.map {|k, v| ":#{k} => #{v}"}.join(', ') + '}'
|
119
|
+
end
|
120
|
+
args << ":labeled => #{labeled}"
|
121
|
+
end
|
122
|
+
t = target == 'self' ? '' : "#{target}."
|
123
|
+
"#{t}#{method_name}(#{args.join ', '})"
|
124
|
+
end
|
125
|
+
|
126
|
+
def direct_action_result(code, options = {})
|
127
|
+
args = options[:bind_args] || [result_name]
|
128
|
+
labeled = options[:labeled] || {}
|
129
|
+
"(#{code.bind args, labeled})"
|
130
|
+
end
|
131
|
+
|
132
|
+
def lookahead
|
133
|
+
(@g << "#{saved_pos_name} = @scanner.pos").newline
|
134
|
+
yield
|
135
|
+
(@g << "@scanner.pos = #{saved_pos_name}").newline
|
136
|
+
end
|
137
|
+
|
53
138
|
end
|
54
|
-
|
139
|
+
|
55
140
|
# @private
|
56
141
|
class TopLevelGenerator < ExprGenerator #:nodoc:
|
57
|
-
include
|
142
|
+
include TopLevelSubGenerating
|
143
|
+
|
144
|
+
def generate(parser)
|
145
|
+
super
|
146
|
+
end
|
58
147
|
end
|
59
|
-
|
148
|
+
|
60
149
|
end
|
@@ -1,45 +1,45 @@
|
|
1
1
|
require 'rattler/back_end/parser_generator'
|
2
2
|
|
3
3
|
module Rattler::BackEnd::ParserGenerator
|
4
|
-
|
4
|
+
|
5
5
|
# @private
|
6
6
|
class LabelGenerator < ExprGenerator #:nodoc:
|
7
7
|
include PredicatePropogating
|
8
8
|
include TokenPropogating
|
9
9
|
include SkipPropogating
|
10
|
-
|
10
|
+
|
11
11
|
def gen_basic(label)
|
12
|
-
generate label.child, :
|
12
|
+
generate label.child, :basic
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def gen_dispatch_action(label, target, method_name)
|
16
|
-
generate label.child, :
|
16
|
+
generate label.child, :dispatch_action, target, method_name
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def gen_direct_action(label, code)
|
20
|
-
generate label.child, :
|
20
|
+
generate label.child, :direct_action, code
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# @private
|
26
26
|
class NestedLabelGenerator < LabelGenerator #:nodoc:
|
27
27
|
include Nested
|
28
|
-
include
|
28
|
+
include NestedSubGenerating
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def LabelGenerator.nested(*args)
|
32
32
|
NestedLabelGenerator.new(*args)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# @private
|
36
36
|
class TopLevelLabelGenerator < LabelGenerator #:nodoc:
|
37
37
|
include TopLevel
|
38
|
-
include
|
38
|
+
include TopLevelSubGenerating
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def LabelGenerator.top_level(*args)
|
42
42
|
TopLevelLabelGenerator.new(*args)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rattler/back_end/parser_generator'
|
2
|
+
|
3
|
+
module Rattler::BackEnd::ParserGenerator
|
4
|
+
|
5
|
+
# @private
|
6
|
+
class List1Generator < ExprGenerator #:nodoc:
|
7
|
+
include ListGenerating
|
8
|
+
include NestedSubGenerating
|
9
|
+
include PredicatePropogating
|
10
|
+
|
11
|
+
def gen_skip_top_level(list)
|
12
|
+
(@g << "#{result_name} = false").newline
|
13
|
+
(@g << "#{saved_pos_name} = nil").newline
|
14
|
+
@g << 'while '
|
15
|
+
generate list.child, :intermediate_skip
|
16
|
+
@g.block '' do
|
17
|
+
(@g << "#{result_name} = true").newline
|
18
|
+
(@g << "#{saved_pos_name} = @scanner.pos").newline
|
19
|
+
@g << 'break unless '
|
20
|
+
generate list.sep_parser, :intermediate_skip
|
21
|
+
end.newline
|
22
|
+
@g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
|
23
|
+
@g.newline << result_name
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def gen_result(captures)
|
29
|
+
@g << captures << " unless #{accumulator_name}.empty?"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# @private
|
35
|
+
class NestedList1Generator < List1Generator #:nodoc:
|
36
|
+
include Nested
|
37
|
+
end
|
38
|
+
|
39
|
+
def List1Generator.nested(*args)
|
40
|
+
NestedList1Generator.new(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @private
|
44
|
+
class TopLevelList1Generator < List1Generator #:nodoc:
|
45
|
+
include TopLevel
|
46
|
+
|
47
|
+
def gen_assert(parser)
|
48
|
+
generate parser.child, :assert_top_level
|
49
|
+
end
|
50
|
+
|
51
|
+
def gen_disallow(parser)
|
52
|
+
generate parser.child, :disallow_top_level
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def List1Generator.top_level(*args)
|
58
|
+
TopLevelList1Generator.new(*args)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rattler/back_end/parser_generator'
|
2
|
+
|
3
|
+
module Rattler::BackEnd::ParserGenerator
|
4
|
+
# @private
|
5
|
+
module ListGenerating #:nodoc:
|
6
|
+
|
7
|
+
def gen_basic_nested(list)
|
8
|
+
atomic_block { gen_basic_top_level list }
|
9
|
+
end
|
10
|
+
|
11
|
+
def gen_basic_top_level(list)
|
12
|
+
list.capturing? ? gen_capturing(list) : gen_skip_top_level(list)
|
13
|
+
end
|
14
|
+
|
15
|
+
def gen_dispatch_action_nested(list, target, method_name)
|
16
|
+
atomic_block do
|
17
|
+
gen_dispatch_action_top_level list, target, method_name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def gen_dispatch_action_top_level(list, target, method_name)
|
22
|
+
gen_capturing list do |a|
|
23
|
+
dispatch_action_result target, method_name,
|
24
|
+
:array_expr => "select_captures(#{a})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def gen_direct_action_nested(list, action)
|
29
|
+
atomic_block do
|
30
|
+
gen_direct_action_top_level list, action
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def gen_direct_action_top_level(list, action)
|
35
|
+
gen_capturing list do |a|
|
36
|
+
direct_action_result action, :bind_args => ["select_captures(#{a})"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def gen_skip_nested(list)
|
41
|
+
atomic_block { gen_skip_top_level list }
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def gen_capturing(list)
|
47
|
+
(@g << "#{accumulator_name} = []").newline
|
48
|
+
(@g << "#{saved_pos_name} = nil").newline
|
49
|
+
@g << "while #{result_name} = "
|
50
|
+
generate list.child, :basic
|
51
|
+
@g.block '' do
|
52
|
+
(@g << "#{saved_pos_name} = @scanner.pos").newline
|
53
|
+
(@g << "#{accumulator_name} << #{result_name}").newline
|
54
|
+
@g << 'break unless '
|
55
|
+
generate list.sep_parser, :intermediate_skip
|
56
|
+
end.newline
|
57
|
+
@g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
|
58
|
+
@g.newline
|
59
|
+
gen_result(block_given? ? yield(accumulator_name) : accumulator_name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def accumulator_name
|
63
|
+
"a#{repeat_level}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def saved_pos_name
|
67
|
+
"lp#{repeat_level}"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rattler/back_end/parser_generator'
|
2
|
+
|
3
|
+
module Rattler::BackEnd::ParserGenerator
|
4
|
+
|
5
|
+
# @private
|
6
|
+
class ListGenerator < ExprGenerator #:nodoc:
|
7
|
+
include ListGenerating
|
8
|
+
include NestedSubGenerating
|
9
|
+
|
10
|
+
def gen_assert(optional)
|
11
|
+
@g << 'true'
|
12
|
+
end
|
13
|
+
|
14
|
+
def gen_disallow(optional)
|
15
|
+
@g << 'false'
|
16
|
+
end
|
17
|
+
|
18
|
+
def gen_skip_top_level(list)
|
19
|
+
(@g << "#{saved_pos_name} = nil").newline
|
20
|
+
@g << 'while '
|
21
|
+
generate list.child, :intermediate_skip
|
22
|
+
@g.block '' do
|
23
|
+
(@g << "#{saved_pos_name} = @scanner.pos").newline
|
24
|
+
@g << 'break unless '
|
25
|
+
generate list.sep_parser, :intermediate_skip
|
26
|
+
end.newline
|
27
|
+
@g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
|
28
|
+
@g.newline << true
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def gen_result(captures)
|
34
|
+
@g << captures
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# @private
|
40
|
+
class NestedListGenerator < ListGenerator #:nodoc:
|
41
|
+
include Nested
|
42
|
+
end
|
43
|
+
|
44
|
+
def ListGenerator.nested(*args)
|
45
|
+
NestedListGenerator.new(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @private
|
49
|
+
class TopLevelListGenerator < ListGenerator #:nodoc:
|
50
|
+
include TopLevel
|
51
|
+
end
|
52
|
+
|
53
|
+
def ListGenerator.top_level(*args)
|
54
|
+
TopLevelListGenerator.new(*args)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|