rattler 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +57 -37
- data/features/command_line/dest_option.feature +8 -21
- data/features/command_line/lib_option.feature +37 -0
- data/features/command_line/parser_generator.feature +7 -4
- data/features/grammar/back_reference.feature +37 -0
- data/features/grammar/fail.feature +3 -3
- data/features/grammar/labels.feature +11 -3
- data/features/grammar/list_matching.feature +14 -5
- data/features/grammar/literal.feature +30 -4
- data/features/grammar/nonterminal.feature +1 -1
- data/features/grammar/ordered_choice.feature +2 -2
- data/features/grammar/skip_operator.feature +1 -1
- data/features/grammar/symantic_action.feature +7 -7
- data/features/grammar/whitespace.feature +2 -2
- data/features/step_definitions/grammar_steps.rb +2 -2
- data/lib/rattler/back_end.rb +1 -0
- data/lib/rattler/back_end/compiler.rb +19 -20
- data/lib/rattler/back_end/optimizer.rb +100 -0
- data/lib/rattler/back_end/optimizer/composite_reducing.rb +18 -0
- data/lib/rattler/back_end/optimizer/flatten_choice.rb +31 -0
- data/lib/rattler/back_end/optimizer/flatten_sequence.rb +59 -0
- data/lib/rattler/back_end/optimizer/flattening.rb +17 -0
- data/lib/rattler/back_end/optimizer/inline_regular_rules.rb +46 -0
- data/lib/rattler/back_end/optimizer/join_match_capturing_sequence.rb +71 -0
- data/lib/rattler/back_end/optimizer/join_match_choice.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_match_matching_sequence.rb +38 -0
- data/lib/rattler/back_end/optimizer/join_match_sequence.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_nested_match.rb +37 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_bare_match.rb +68 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_match.rb +17 -0
- data/lib/rattler/back_end/optimizer/join_predicate_or_nested_match.rb +36 -0
- data/lib/rattler/back_end/optimizer/match_joining.rb +60 -0
- data/lib/rattler/back_end/optimizer/optimization.rb +94 -0
- data/lib/rattler/back_end/optimizer/optimization_context.rb +72 -0
- data/lib/rattler/back_end/optimizer/optimization_sequence.rb +37 -0
- data/lib/rattler/back_end/optimizer/optimize_children.rb +46 -0
- data/lib/rattler/back_end/optimizer/reduce_repeat_match.rb +44 -0
- data/lib/rattler/back_end/optimizer/remove_meaningless_wrapper.rb +32 -0
- data/lib/rattler/back_end/optimizer/simplify_redundant_repeat.rb +43 -0
- data/lib/rattler/back_end/optimizer/simplify_token_match.rb +38 -0
- data/lib/rattler/back_end/parser_generator.rb +21 -14
- data/lib/rattler/back_end/parser_generator/apply_generator.rb +35 -35
- data/lib/rattler/back_end/parser_generator/assert_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/back_reference_generator.rb +93 -0
- data/lib/rattler/back_end/parser_generator/choice_generator.rb +33 -49
- data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +14 -14
- data/lib/rattler/back_end/parser_generator/disallow_generator.rb +29 -30
- data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +11 -13
- data/lib/rattler/back_end/parser_generator/expr_generator.rb +36 -56
- data/lib/rattler/back_end/parser_generator/fail_generator.rb +18 -18
- data/lib/rattler/back_end/parser_generator/group_match.rb +18 -0
- data/lib/rattler/back_end/parser_generator/group_match_generator.rb +76 -0
- data/lib/rattler/back_end/parser_generator/label_generator.rb +25 -6
- data/lib/rattler/back_end/parser_generator/list1_generator.rb +7 -7
- data/lib/rattler/back_end/parser_generator/list_generating.rb +19 -20
- data/lib/rattler/back_end/parser_generator/list_generator.rb +5 -5
- data/lib/rattler/back_end/parser_generator/match_generator.rb +52 -52
- data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +6 -6
- data/lib/rattler/back_end/parser_generator/optional_generator.rb +30 -29
- data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +8 -8
- data/lib/rattler/back_end/parser_generator/repeat_generating.rb +23 -25
- data/lib/rattler/back_end/parser_generator/rule_generator.rb +27 -79
- data/lib/rattler/back_end/parser_generator/rule_set_generator.rb +102 -0
- data/lib/rattler/back_end/parser_generator/sequence_generator.rb +49 -41
- data/lib/rattler/back_end/parser_generator/skip_generator.rb +14 -20
- data/lib/rattler/back_end/parser_generator/skip_propogating.rb +4 -4
- data/lib/rattler/back_end/parser_generator/sub_generating.rb +6 -0
- data/lib/rattler/back_end/parser_generator/token_generator.rb +12 -12
- data/lib/rattler/back_end/parser_generator/token_propogating.rb +2 -2
- data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +4 -4
- data/lib/rattler/grammar.rb +4 -3
- data/lib/rattler/grammar/analysis.rb +91 -0
- data/lib/rattler/grammar/grammar.rb +37 -25
- data/lib/rattler/grammar/grammar_parser.rb +19 -11
- data/lib/rattler/grammar/metagrammar.rb +569 -800
- data/lib/rattler/grammar/rattler.rtlr +162 -144
- data/lib/rattler/parsers.rb +5 -1
- data/lib/rattler/parsers/action_code.rb +29 -15
- data/lib/rattler/parsers/apply.rb +5 -5
- data/lib/rattler/parsers/assert.rb +4 -18
- data/lib/rattler/parsers/back_reference.rb +46 -0
- data/lib/rattler/parsers/choice.rb +6 -39
- data/lib/rattler/parsers/combinator_parser.rb +32 -0
- data/lib/rattler/parsers/combining.rb +3 -29
- data/lib/rattler/parsers/direct_action.rb +27 -30
- data/lib/rattler/parsers/disallow.rb +4 -18
- data/lib/rattler/parsers/dispatch_action.rb +30 -25
- data/lib/rattler/parsers/label.rb +9 -18
- data/lib/rattler/parsers/list.rb +3 -34
- data/lib/rattler/parsers/list1.rb +4 -36
- data/lib/rattler/parsers/list_parser.rb +64 -0
- data/lib/rattler/parsers/match.rb +7 -42
- data/lib/rattler/parsers/node_code.rb +44 -0
- data/lib/rattler/parsers/one_or_more.rb +7 -27
- data/lib/rattler/parsers/optional.rb +5 -25
- data/lib/rattler/parsers/parser.rb +16 -44
- data/lib/rattler/parsers/parser_dsl.rb +13 -3
- data/lib/rattler/parsers/predicate.rb +4 -12
- data/lib/rattler/parsers/rule.rb +18 -19
- data/lib/rattler/parsers/rule_set.rb +63 -0
- data/lib/rattler/parsers/sequence.rb +12 -46
- data/lib/rattler/parsers/skip.rb +12 -26
- data/lib/rattler/parsers/token.rb +6 -21
- data/lib/rattler/parsers/zero_or_more.rb +6 -26
- data/lib/rattler/runner.rb +66 -28
- data/lib/rattler/runtime/extended_packrat_parser.rb +26 -20
- data/lib/rattler/runtime/packrat_parser.rb +17 -21
- data/lib/rattler/runtime/parser.rb +12 -2
- data/lib/rattler/runtime/recursive_descent_parser.rb +3 -11
- data/lib/rattler/util.rb +2 -1
- data/lib/rattler/util/graphviz.rb +29 -0
- data/lib/rattler/util/graphviz/digraph_builder.rb +71 -0
- data/lib/rattler/util/graphviz/node_builder.rb +84 -0
- data/lib/rattler/util/node.rb +37 -19
- data/lib/rattler/util/parser_spec_helper.rb +61 -35
- data/spec/rattler/back_end/compiler_spec.rb +6 -860
- data/spec/rattler/back_end/optimizer/flatten_choice_spec.rb +70 -0
- data/spec/rattler/back_end/optimizer/flatten_sequence_spec.rb +130 -0
- data/spec/rattler/back_end/optimizer/inline_regular_rules_spec.rb +80 -0
- data/spec/rattler/back_end/optimizer/join_match_capturing_sequence_spec.rb +241 -0
- data/spec/rattler/back_end/optimizer/join_match_choice_spec.rb +100 -0
- data/spec/rattler/back_end/optimizer/join_match_matching_sequence_spec.rb +112 -0
- data/spec/rattler/back_end/optimizer/join_predicate_bare_match_spec.rb +194 -0
- data/spec/rattler/back_end/optimizer/join_predicate_nested_match_spec.rb +180 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_bare_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/join_predicate_or_nested_match_spec.rb +153 -0
- data/spec/rattler/back_end/optimizer/reduce_repeat_match_spec.rb +98 -0
- data/spec/rattler/back_end/optimizer/simplify_redundant_repeat_spec.rb +226 -0
- data/spec/rattler/back_end/optimizer/simplify_token_match_spec.rb +85 -0
- data/spec/rattler/back_end/parser_generator/apply_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/assert_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/back_reference_generator_spec.rb +181 -0
- data/spec/rattler/back_end/parser_generator/choice_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/direct_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/disallow_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/dispatch_action_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/group_match_generator_spec.rb +185 -0
- data/spec/rattler/back_end/parser_generator/label_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +10 -5
- data/spec/rattler/back_end/parser_generator/match_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/one_or_more_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/optional_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/rule_generator_spec.rb +13 -46
- data/spec/rattler/back_end/parser_generator/rule_set_generator_spec.rb +97 -0
- data/spec/rattler/back_end/parser_generator/sequence_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/skip_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/token_generator_spec.rb +38 -33
- data/spec/rattler/back_end/parser_generator/zero_or_more_generator_spec.rb +39 -34
- data/spec/rattler/back_end/shared_compiler_examples.rb +885 -0
- data/spec/rattler/grammar/analysis_spec.rb +167 -0
- data/spec/rattler/grammar/grammar_parser_spec.rb +169 -179
- data/spec/rattler/grammar/grammar_spec.rb +24 -21
- data/spec/rattler/parsers/action_code_spec.rb +64 -19
- data/spec/rattler/parsers/apply_spec.rb +9 -9
- data/spec/rattler/parsers/back_reference_spec.rb +38 -0
- data/spec/rattler/parsers/combinator_parser_spec.rb +14 -0
- data/spec/rattler/parsers/direct_action_spec.rb +16 -2
- data/spec/rattler/parsers/dispatch_action_spec.rb +15 -32
- data/spec/rattler/parsers/fail_spec.rb +6 -4
- data/spec/rattler/parsers/label_spec.rb +10 -28
- data/spec/rattler/parsers/node_code_spec.rb +48 -0
- data/spec/rattler/parsers/parser_dsl_spec.rb +1 -1
- data/spec/rattler/parsers/rule_set_spec.rb +35 -0
- data/spec/rattler/parsers/sequence_spec.rb +15 -24
- data/spec/rattler/runtime/extended_packrat_parser_spec.rb +22 -17
- data/spec/rattler/runtime/packrat_parser_spec.rb +1 -1
- data/spec/rattler/runtime/parse_node_spec.rb +15 -19
- data/spec/rattler/runtime/recursive_descent_parser_spec.rb +1 -1
- data/spec/rattler/runtime/shared_parser_examples.rb +61 -28
- data/spec/rattler/util/graphviz/node_builder_spec.rb +84 -0
- data/spec/rattler/util/node_spec.rb +92 -65
- data/spec/rattler_spec.rb +16 -16
- data/spec/support/combinator_parser_spec_helper.rb +19 -18
- data/spec/support/compiler_spec_helper.rb +56 -87
- data/spec/support/runtime_parser_spec_helper.rb +6 -14
- metadata +117 -22
- data/features/grammar/regex.feature +0 -24
- data/lib/rattler/parsers/match_joining.rb +0 -67
- data/lib/rattler/parsers/rules.rb +0 -43
@@ -0,0 +1,46 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/parsers/back_reference.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rattler/parsers'
|
9
|
+
|
10
|
+
module Rattler::Parsers
|
11
|
+
#
|
12
|
+
# +BackReference+ matches the labeled result of an earlier match.
|
13
|
+
#
|
14
|
+
# @author Jason Arhart
|
15
|
+
#
|
16
|
+
class BackReference < Parser
|
17
|
+
|
18
|
+
def self.[](ref_label)
|
19
|
+
self.new(:ref_label => ref_label.to_sym)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parsed(results, *_)
|
23
|
+
self[results.first[1..-1]]
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(scanner, rules, scope={})
|
27
|
+
scanner.scan Regexp.compile(Regexp.escape scope[ref_label])
|
28
|
+
end
|
29
|
+
|
30
|
+
def re_expr(scope)
|
31
|
+
"/#{re_source scope}/"
|
32
|
+
end
|
33
|
+
|
34
|
+
def re_source(scope)
|
35
|
+
'#{' + Regexp.escape(scope[ref_label].to_s) + '}'
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param (see Parser#with_ws)
|
39
|
+
# @return (see Parser#with_ws)
|
40
|
+
def with_ws(ws)
|
41
|
+
ws.skip & self
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -16,27 +16,26 @@ module Rattler::Parsers
|
|
16
16
|
#
|
17
17
|
class Choice < Parser
|
18
18
|
include Combining
|
19
|
-
|
20
|
-
|
19
|
+
|
21
20
|
# @private
|
22
21
|
def self.parsed(results, *_) #:nodoc:
|
23
22
|
results.reduce(:|)
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
# Try each parser in order until one succeeds and return that result.
|
27
26
|
#
|
28
27
|
# @param (see Parser#parse_labeled)
|
29
28
|
#
|
30
29
|
# @return the result of the first parser that matches, or +false+
|
31
|
-
def parse(scanner, rules,
|
30
|
+
def parse(scanner, rules, scope = {})
|
32
31
|
for child in children
|
33
|
-
if r = child.
|
32
|
+
if r = child.parse(scanner, rules, scope)
|
34
33
|
return r
|
35
34
|
end
|
36
35
|
end
|
37
36
|
false
|
38
37
|
end
|
39
|
-
|
38
|
+
|
40
39
|
# Return a new parser that tries this parser first and if it fails tries
|
41
40
|
# +other+.
|
42
41
|
#
|
@@ -45,38 +44,6 @@ module Rattler::Parsers
|
|
45
44
|
def |(other)
|
46
45
|
Choice[(children + [other])]
|
47
46
|
end
|
48
|
-
|
49
|
-
protected
|
50
|
-
|
51
|
-
def optimized_children
|
52
|
-
join_matches super
|
53
|
-
end
|
54
|
-
|
55
|
-
def token_optimized_children
|
56
|
-
join_matches super
|
57
|
-
end
|
58
|
-
|
59
|
-
def skip_optimized_children
|
60
|
-
join_matches super
|
61
|
-
end
|
62
|
-
|
63
|
-
def match_join(matches)
|
64
|
-
matches.map {|_| _.re.source }.join('|')
|
65
|
-
end
|
66
|
-
|
67
|
-
def join_matches(parsers)
|
68
|
-
super flatten_choices(parsers)
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def flatten_choices(parsers)
|
74
|
-
if parsers.all? {|_| Choice === _ }
|
75
|
-
parsers.map {|_| _.to_a }.reduce(:+)
|
76
|
-
else
|
77
|
-
parsers
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
47
|
+
|
81
48
|
end
|
82
49
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/parsers/rule_set.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rattler/parsers'
|
9
|
+
|
10
|
+
module Rattler::Parsers
|
11
|
+
class CombinatorParser < Rattler::Runtime::Parser
|
12
|
+
|
13
|
+
def self.as_class(start_rule, rule_set)
|
14
|
+
new_class = Class.new(self)
|
15
|
+
new_class.send :define_method, :initialize do |source|
|
16
|
+
super source, start_rule, rule_set
|
17
|
+
end
|
18
|
+
new_class
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(source, start_rule, rule_set)
|
22
|
+
super source
|
23
|
+
@start_rule = start_rule
|
24
|
+
@rule_set = rule_set
|
25
|
+
end
|
26
|
+
|
27
|
+
def __parse__
|
28
|
+
@start_rule.parse(@scanner, @rule_set)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -8,40 +8,14 @@
|
|
8
8
|
module Rattler::Parsers
|
9
9
|
# @private
|
10
10
|
module Combining #:nodoc:
|
11
|
-
|
11
|
+
|
12
12
|
def capturing?
|
13
13
|
@capturing ||= any? {|child| child.capturing? }
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def with_ws(ws)
|
17
17
|
self.class.new(children.map {|_| _.with_ws(ws) }, attrs)
|
18
18
|
end
|
19
|
-
|
20
|
-
def optimized
|
21
|
-
self.class.new(optimized_children, attrs)
|
22
|
-
end
|
23
|
-
|
24
|
-
def token_optimized
|
25
|
-
self.class.new(token_optimized_children, attrs)
|
26
|
-
end
|
27
|
-
|
28
|
-
def skip_optimized
|
29
|
-
self.class.new(skip_optimized_children, attrs)
|
30
|
-
end
|
31
|
-
|
32
|
-
protected
|
33
|
-
|
34
|
-
def optimized_children
|
35
|
-
children.map {|_| _.optimized }
|
36
|
-
end
|
37
|
-
|
38
|
-
def token_optimized_children
|
39
|
-
children.map {|_| _.token_optimized }
|
40
|
-
end
|
41
|
-
|
42
|
-
def skip_optimized_children
|
43
|
-
children.map {|_| _.skip_optimized }
|
44
|
-
end
|
45
|
-
|
19
|
+
|
46
20
|
end
|
47
21
|
end
|
@@ -16,16 +16,16 @@ module Rattler::Parsers
|
|
16
16
|
#
|
17
17
|
class DirectAction < Parser
|
18
18
|
include Combining
|
19
|
-
|
19
|
+
|
20
20
|
def self.[](child, code)
|
21
21
|
self.new(child, :code => code)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# @private
|
25
25
|
def self.parsed(results, *_) #:nodoc:
|
26
26
|
self[*results]
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# If the wrapped parser matches at the parse position, return the result
|
30
30
|
# of applying the symantic action, otherwise return a false value.
|
31
31
|
#
|
@@ -33,48 +33,45 @@ module Rattler::Parsers
|
|
33
33
|
#
|
34
34
|
# @return the result of applying the symantic action, or a false value if
|
35
35
|
# the parse failed.
|
36
|
-
def parse(scanner, rules,
|
37
|
-
|
38
|
-
if result = child.parse(scanner, rules, labeled)
|
36
|
+
def parse(scanner, rules, scope = {})
|
37
|
+
if result = parse_child(child, scanner, rules, scope) {|_| scope = _ }
|
39
38
|
if not capturing?
|
40
39
|
apply([])
|
41
40
|
elsif result.respond_to?(:to_ary)
|
42
|
-
apply(result,
|
41
|
+
apply(result, scope)
|
43
42
|
else
|
44
|
-
apply([result],
|
43
|
+
apply([result], scope)
|
45
44
|
end
|
46
45
|
end
|
47
46
|
end
|
48
|
-
|
47
|
+
|
49
48
|
def bindable_code
|
50
49
|
@bindable_code ||= ActionCode.new(code)
|
51
50
|
end
|
52
|
-
|
53
|
-
def bind(
|
54
|
-
bindable_code.bind(
|
55
|
-
end
|
56
|
-
|
57
|
-
# @private
|
58
|
-
def token_optimized #:nodoc:
|
59
|
-
child.token_optimized
|
60
|
-
end
|
61
|
-
|
62
|
-
# @private
|
63
|
-
def skip_optimized #:nodoc:
|
64
|
-
child.skip_optimized
|
51
|
+
|
52
|
+
def bind(scope, bind_args)
|
53
|
+
bindable_code.bind(scope, bind_args)
|
65
54
|
end
|
66
|
-
|
55
|
+
|
67
56
|
private
|
68
|
-
|
69
|
-
def
|
70
|
-
|
71
|
-
|
57
|
+
|
58
|
+
def parse_child(child, scanner, rules, scope)
|
59
|
+
if child.is_a? Sequence
|
60
|
+
child.parse_and_yield_scope(scanner, rules, scope) {|_| yield _ }
|
61
|
+
else
|
62
|
+
child.parse(scanner, rules, scope) {|_| yield _ }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def apply(results, scope={})
|
67
|
+
code_scope = {}
|
68
|
+
scope.each {|k, v| code_scope[k] = v.inspect }
|
72
69
|
if child.variable_capture_count?
|
73
|
-
eval(bind([results.inspect]
|
70
|
+
eval(bind(code_scope, [results.inspect]))
|
74
71
|
else
|
75
|
-
eval(bind(results.map {|_| _.inspect }
|
72
|
+
eval(bind(code_scope, results.map {|_| _.inspect }))
|
76
73
|
end
|
77
74
|
end
|
78
|
-
|
75
|
+
|
79
76
|
end
|
80
77
|
end
|
@@ -13,33 +13,19 @@ module Rattler::Parsers
|
|
13
13
|
# and vice versa.
|
14
14
|
#
|
15
15
|
class Disallow < Predicate
|
16
|
-
|
16
|
+
|
17
17
|
# Succeed and return +true+ if and only if decorated parser fails. Never
|
18
18
|
# consumes any input.
|
19
19
|
#
|
20
20
|
# @param (see Parser#parse_labeled)
|
21
21
|
#
|
22
22
|
# @return [Boolean] +true+ if the decorated parser fails
|
23
|
-
def parse(scanner, rules,
|
23
|
+
def parse(scanner, rules, scope = {})
|
24
24
|
pos = scanner.pos
|
25
|
-
result = !child.parse(scanner, rules)
|
25
|
+
result = !child.parse(scanner, rules, scope)
|
26
26
|
scanner.pos = pos
|
27
27
|
result
|
28
28
|
end
|
29
|
-
|
30
|
-
# Return a parser that parses identically but may have a more optimized
|
31
|
-
# structure.
|
32
|
-
#
|
33
|
-
# @return a parser that parses identically but may have a more optimized
|
34
|
-
# structure
|
35
|
-
def optimized
|
36
|
-
Disallow[child.optimized]
|
37
|
-
end
|
38
|
-
|
39
|
-
# @private
|
40
|
-
def as_match #:nodoc:
|
41
|
-
Match[child.disallow_re] if Match === child
|
42
|
-
end
|
43
|
-
|
29
|
+
|
44
30
|
end
|
45
31
|
end
|
@@ -16,19 +16,19 @@ module Rattler::Parsers
|
|
16
16
|
#
|
17
17
|
class DispatchAction < Parser
|
18
18
|
include Combining
|
19
|
-
|
19
|
+
|
20
20
|
# @private
|
21
21
|
@@node_defaults = {
|
22
22
|
:target => 'Rattler::Runtime::ParseNode',
|
23
23
|
:method => 'parsed'
|
24
24
|
}
|
25
|
-
|
25
|
+
|
26
26
|
# @private
|
27
27
|
def self.parsed(results, *_) #:nodoc:
|
28
28
|
attributed, optional_attribute = results
|
29
29
|
self[attributed, optional_attribute.first || @@node_defaults[:target]]
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# @private
|
33
33
|
def self.parse_attrs_arg(arg) #:nodoc:
|
34
34
|
case arg
|
@@ -40,7 +40,7 @@ module Rattler::Parsers
|
|
40
40
|
{ :target => arg.to_s.strip }
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# Create a new parser that decorates a parser to peform a symantic
|
45
45
|
# on success.
|
46
46
|
#
|
@@ -60,10 +60,10 @@ module Rattler::Parsers
|
|
60
60
|
@@node_defaults.each {|k, v| attrs[k] ||= v } unless attrs[:code]
|
61
61
|
@method_name = attrs[:method]
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# the name of the method used as the symantic action
|
65
65
|
attr_reader :method_name
|
66
|
-
|
66
|
+
|
67
67
|
# If the wrapped parser matches at the parse position, return the result
|
68
68
|
# of applying the symantic action, otherwise return a false value.
|
69
69
|
#
|
@@ -71,39 +71,44 @@ module Rattler::Parsers
|
|
71
71
|
#
|
72
72
|
# @return the result of applying the symantic action, or a false value if
|
73
73
|
# the parse failed.
|
74
|
-
def parse(scanner, rules,
|
75
|
-
|
76
|
-
if result = child.parse(scanner, rules, labeled)
|
74
|
+
def parse(scanner, rules, scope = {})
|
75
|
+
if result = parse_child(child, scanner, rules, scope) {|_| scope = _ }
|
77
76
|
if not capturing?
|
78
77
|
apply([])
|
79
78
|
elsif result.respond_to?(:to_ary)
|
80
|
-
apply(result,
|
79
|
+
apply(result, scope)
|
81
80
|
else
|
82
|
-
apply([result],
|
81
|
+
apply([result], scope)
|
83
82
|
end
|
84
83
|
end
|
85
84
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
child.token_optimized
|
85
|
+
|
86
|
+
def bindable_code
|
87
|
+
@bindable_code ||= NodeCode.new(target, method_name)
|
90
88
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
child.skip_optimized
|
89
|
+
|
90
|
+
def bind(scope, bind_args)
|
91
|
+
bindable_code.bind(scope, bind_args)
|
95
92
|
end
|
96
|
-
|
93
|
+
|
97
94
|
private
|
98
|
-
|
99
|
-
def
|
100
|
-
|
95
|
+
|
96
|
+
def parse_child(child, scanner, rules, scope)
|
97
|
+
if child.is_a? Sequence
|
98
|
+
child.parse_and_yield_scope(scanner, rules, scope) {|_| yield _ }
|
99
|
+
else
|
100
|
+
child.parse(scanner, rules, scope) {|_| yield _ }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def apply(results, scope={})
|
105
|
+
attrs = scope.empty? ? {} : {:labeled => scope}
|
101
106
|
target_class.send method_name, results, attrs
|
102
107
|
end
|
103
|
-
|
108
|
+
|
104
109
|
def target_class
|
105
110
|
@target_class ||= target.split('::').inject(Kernel, :const_get)
|
106
111
|
end
|
107
|
-
|
112
|
+
|
108
113
|
end
|
109
114
|
end
|
@@ -17,45 +17,36 @@ module Rattler::Parsers
|
|
17
17
|
#
|
18
18
|
class Label < Parser
|
19
19
|
include Combining
|
20
|
-
|
20
|
+
|
21
21
|
# @private
|
22
22
|
def self.parsed(results, *_) #:nodoc:
|
23
23
|
self[*results]
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Create a new parser that decorates +parser+ and associates +label+ with
|
27
27
|
# +parser+'s parse result on success.
|
28
28
|
def self.[](label, parser)
|
29
29
|
self.new(parser, :label => label.to_sym)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# Always +true+
|
33
33
|
# @return true
|
34
34
|
def labeled?
|
35
35
|
true
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
# Delegate to the decorated parser and associate #label with the parse
|
39
39
|
# result if successful.
|
40
40
|
#
|
41
41
|
# @param (see Parser#parse_labeled)
|
42
42
|
#
|
43
43
|
# @return the decorated parser's parse result
|
44
|
-
def parse(scanner, rules,
|
45
|
-
child.parse(scanner, rules,
|
46
|
-
|
47
|
-
|
48
|
-
# Parse and on success associate the label with the parse result if
|
49
|
-
# +capturing?+.
|
50
|
-
#
|
51
|
-
# @param (see Parser#parse_labeled)
|
52
|
-
# @return (see Parser#parse_labeled)
|
53
|
-
def parse_labeled(scanner, rules, labeled)
|
54
|
-
if r = super
|
55
|
-
labeled[label] = r if capturing?
|
56
|
-
r
|
44
|
+
def parse(scanner, rules, scope = {})
|
45
|
+
if result = child.parse(scanner, rules, scope) {|_| scope = _ }
|
46
|
+
yield scope.merge(label => result) if block_given?
|
47
|
+
result
|
57
48
|
end
|
58
49
|
end
|
59
|
-
|
50
|
+
|
60
51
|
end
|
61
52
|
end
|