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
@@ -20,7 +20,7 @@ module Rattler
|
|
20
20
|
#
|
21
21
|
# @option options [Parser] ws (nil) a parser to be used to skip whitespace
|
22
22
|
#
|
23
|
-
# @return [Rattler::Parsers::
|
23
|
+
# @return [Rattler::Parsers::RuleSet] a set of parse rules
|
24
24
|
#
|
25
25
|
def self.rules(options = {}, &block)
|
26
26
|
self.new(options).rules(&block)
|
@@ -48,10 +48,10 @@ module Rattler
|
|
48
48
|
|
49
49
|
# Evaluate the given block to define parse rules
|
50
50
|
#
|
51
|
-
# @return [
|
51
|
+
# @return [RuleSet] the rules defined in the block
|
52
52
|
def rules(&block)
|
53
53
|
instance_exec(self, &block)
|
54
|
-
|
54
|
+
RuleSet[@rules]
|
55
55
|
end
|
56
56
|
|
57
57
|
# Evaluate the given block to define a parse rule
|
@@ -104,6 +104,7 @@ module Rattler
|
|
104
104
|
when :SPACE then match /[[:space:]]/
|
105
105
|
when :UPPER then match /[[:upper:]]/
|
106
106
|
when :XDIGIT then match /[[:xdigit:]]/
|
107
|
+
when :WORD then match /[[:alnum:]_]/
|
107
108
|
when Symbol then Apply[arg]
|
108
109
|
else match Regexp.new(Regexp.escape(arg.to_s))
|
109
110
|
end
|
@@ -133,6 +134,8 @@ module Rattler
|
|
133
134
|
ZeroOrMore[to_parser(arg)]
|
134
135
|
end
|
135
136
|
|
137
|
+
alias_method :any, :zero_or_more
|
138
|
+
|
136
139
|
# Create a new one-or-more parser.
|
137
140
|
#
|
138
141
|
# @overload one_or_more(parser)
|
@@ -145,6 +148,8 @@ module Rattler
|
|
145
148
|
OneOrMore[to_parser(arg)]
|
146
149
|
end
|
147
150
|
|
151
|
+
alias_method :some, :one_or_more
|
152
|
+
|
148
153
|
# Create a new list parser.
|
149
154
|
#
|
150
155
|
# @overload list(term_parser, sep_parser)
|
@@ -343,6 +348,11 @@ module Rattler
|
|
343
348
|
match :XDIGIT
|
344
349
|
end
|
345
350
|
|
351
|
+
# @return [Match] a parser matching the +word+ character class
|
352
|
+
def word
|
353
|
+
match :WORD
|
354
|
+
end
|
355
|
+
|
346
356
|
private
|
347
357
|
|
348
358
|
def to_parser(o)
|
@@ -10,26 +10,18 @@ require 'rattler/parsers'
|
|
10
10
|
module Rattler::Parsers
|
11
11
|
# @private
|
12
12
|
class Predicate < Parser #:nodoc:
|
13
|
-
|
13
|
+
|
14
14
|
def self.parsed(results, *_)
|
15
15
|
self[results.first]
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def capturing?
|
19
19
|
false
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def with_ws(ws)
|
23
23
|
self.class.new(child.with_ws(ws), attrs)
|
24
24
|
end
|
25
|
-
|
26
|
-
def token_optimized
|
27
|
-
optimized
|
28
|
-
end
|
29
|
-
|
30
|
-
def skip_optimized
|
31
|
-
optimized
|
32
|
-
end
|
33
|
-
|
25
|
+
|
34
26
|
end
|
35
27
|
end
|
data/lib/rattler/parsers/rule.rb
CHANGED
@@ -15,22 +15,19 @@ module Rattler::Parsers
|
|
15
15
|
# @author Jason Arhart
|
16
16
|
#
|
17
17
|
class Rule < Rattler::Util::Node
|
18
|
-
|
19
|
-
# @private
|
20
|
-
def self.parsed(results, *_) #:nodoc:
|
21
|
-
self[*results]
|
22
|
-
end
|
23
|
-
|
18
|
+
|
24
19
|
# Create a new +Rule+.
|
25
20
|
#
|
26
21
|
# @param [Symbol, String] name the name of the new rule
|
27
22
|
# @param [Parser] parser the parser that defines the rule body
|
28
23
|
#
|
29
24
|
# @return [Rule] a new parse rule
|
30
|
-
def self.[](name, parser)
|
31
|
-
self.new(parser, :name => name.to_sym)
|
25
|
+
def self.[](name, parser, attrs={})
|
26
|
+
self.new(parser, attrs.merge(:name => name.to_sym))
|
32
27
|
end
|
33
|
-
|
28
|
+
|
29
|
+
alias_method :expr, :child
|
30
|
+
|
34
31
|
# Parse using +scanner+ and +rules+ and on success return the result, on
|
35
32
|
# failure return a false value.
|
36
33
|
#
|
@@ -38,20 +35,22 @@ module Rattler::Parsers
|
|
38
35
|
# @param rules (see Parser#parse_labeled)
|
39
36
|
#
|
40
37
|
# @return (see Parser#parse_labeled)
|
41
|
-
def parse(scanner, rules)
|
42
|
-
|
38
|
+
def parse(scanner, rules, scope = {})
|
39
|
+
catch(:rule_failed) do
|
40
|
+
return expr.parse(scanner, rules, scope)
|
41
|
+
end
|
42
|
+
false
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
|
+
def with_expr(new_expr)
|
46
|
+
Rule[name, new_expr, attrs]
|
47
|
+
end
|
48
|
+
|
45
49
|
# @param (see Parser#with_ws)
|
46
50
|
# @return (see Parser#with_ws)
|
47
51
|
def with_ws(ws)
|
48
|
-
|
52
|
+
self.with_expr expr.with_ws(ws)
|
49
53
|
end
|
50
|
-
|
51
|
-
# @return (see Parser#optimized)
|
52
|
-
def optimized
|
53
|
-
Rule[name, child.optimized]
|
54
|
-
end
|
55
|
-
|
54
|
+
|
56
55
|
end
|
57
56
|
end
|
@@ -0,0 +1,63 @@
|
|
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 RuleSet < Rattler::Util::Node
|
12
|
+
|
13
|
+
# @private
|
14
|
+
def self.parsed(results, *_) #:nodoc:
|
15
|
+
self.new(results)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
super
|
20
|
+
@by_name = {}
|
21
|
+
children.each {|rule| @by_name[rule.name] = rule }
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :rules, :children
|
25
|
+
|
26
|
+
def start_rule
|
27
|
+
attrs[:start_rule]
|
28
|
+
end
|
29
|
+
|
30
|
+
def rule(name)
|
31
|
+
@by_name[name]
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](*args)
|
35
|
+
if args.length == 1 and args[0].is_a?(Symbol)
|
36
|
+
rule(args[0])
|
37
|
+
else
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def with_attrs(new_attrs)
|
43
|
+
self.class.new(children, attrs.merge(new_attrs))
|
44
|
+
end
|
45
|
+
|
46
|
+
def with_rules(new_rules)
|
47
|
+
self.class.new(new_rules, attrs)
|
48
|
+
end
|
49
|
+
|
50
|
+
def map_rules
|
51
|
+
self.with_rules rules.map {|_| yield _ }
|
52
|
+
end
|
53
|
+
|
54
|
+
def select_rules
|
55
|
+
self.with_rules rules.select {|_| yield _ }
|
56
|
+
end
|
57
|
+
|
58
|
+
def analysis
|
59
|
+
@analysis ||= Rattler::Grammar::Analysis.new(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -16,13 +16,12 @@ module Rattler::Parsers
|
|
16
16
|
#
|
17
17
|
class Sequence < 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 sequence, and if they all succeed return an array of
|
27
26
|
# captured results, or return +false+ if any parser fails.
|
28
27
|
#
|
@@ -30,24 +29,29 @@ module Rattler::Parsers
|
|
30
29
|
#
|
31
30
|
# @return an array of captured results of each parser in sequence, or
|
32
31
|
# +false+
|
33
|
-
def parse(scanner, rules,
|
32
|
+
def parse(scanner, rules, scope = {})
|
33
|
+
parse_and_yield_scope scanner, rules, scope
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_and_yield_scope(scanner, rules, scope = {})
|
34
37
|
pos = scanner.pos
|
35
38
|
results = []
|
36
39
|
for child in children
|
37
|
-
if r = child.
|
40
|
+
if r = child.parse(scanner, rules, scope) {|_| scope = _ }
|
38
41
|
results << r unless r == true
|
39
42
|
else
|
40
43
|
scanner.pos = pos
|
41
44
|
return false
|
42
45
|
end
|
43
46
|
end
|
47
|
+
yield scope if block_given?
|
44
48
|
case capture_count
|
45
49
|
when 0 then true
|
46
50
|
when 1 then results[0]
|
47
51
|
else results
|
48
52
|
end
|
49
53
|
end
|
50
|
-
|
54
|
+
|
51
55
|
# Return a new parser that tries both this parser and +other+ and fails
|
52
56
|
# unless both parse in sequence.
|
53
57
|
#
|
@@ -56,51 +60,13 @@ module Rattler::Parsers
|
|
56
60
|
def &(other)
|
57
61
|
Sequence[(children + [other])]
|
58
62
|
end
|
59
|
-
|
63
|
+
|
60
64
|
# The number of child parsers that are capturing
|
61
65
|
#
|
62
66
|
# @return the number of child parsers that are capturing
|
63
67
|
def capture_count
|
64
68
|
@capture_count ||= count {|_| _.capturing? }
|
65
69
|
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
|
69
|
-
def optimized_children
|
70
|
-
oc = super
|
71
|
-
if oc.count {|_| _.capturing? } == 1
|
72
|
-
flattened = flatten_sequences oc
|
73
|
-
if flattened.count {|_| _.capturing? } == 1
|
74
|
-
join_matches flattened
|
75
|
-
else
|
76
|
-
join_matches oc
|
77
|
-
end
|
78
|
-
else
|
79
|
-
oc
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def token_optimized_children
|
84
|
-
join_matches flatten_sequences(super)
|
85
|
-
end
|
86
|
-
|
87
|
-
def skip_optimized_children
|
88
|
-
join_matches flatten_sequences(super)
|
89
|
-
end
|
90
|
-
|
91
|
-
def match_join(matches)
|
92
|
-
matches.map {|_| _.atomic_re.source }.join
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def flatten_sequences(parsers)
|
98
|
-
if parsers.all? {|_| Sequence === _ }
|
99
|
-
parsers.map {|_| _.to_a }.reduce(:+)
|
100
|
-
else
|
101
|
-
parsers
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
70
|
+
|
105
71
|
end
|
106
72
|
end
|
data/lib/rattler/parsers/skip.rb
CHANGED
@@ -13,12 +13,12 @@ module Rattler::Parsers
|
|
13
13
|
# the results
|
14
14
|
#
|
15
15
|
class Skip < Parser
|
16
|
-
|
16
|
+
|
17
17
|
# @private
|
18
18
|
def self.parsed(results, *_) #:nodoc:
|
19
19
|
self[results.first]
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# If the decorated parser matches return +true+, otherwise return a false
|
23
23
|
# value.
|
24
24
|
#
|
@@ -26,43 +26,29 @@ module Rattler::Parsers
|
|
26
26
|
#
|
27
27
|
# @return [Boolean] +true+ if the decorated parser matches at the parse
|
28
28
|
# position
|
29
|
-
def parse(scanner, rules,
|
30
|
-
child.parse(scanner, rules) && true
|
29
|
+
def parse(scanner, rules, scope = {})
|
30
|
+
child.parse(scanner, rules, scope) && true
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# Always +false+
|
34
34
|
# @return false
|
35
35
|
def capturing?
|
36
36
|
false
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Return a new parser that uses +ws+ to skip whitespace before matching
|
40
40
|
# tokens.
|
41
41
|
#
|
42
42
|
# @param (see Parser#with_ws)
|
43
43
|
# @return (see Parser#with_ws)
|
44
44
|
def with_ws(ws)
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
# Return a parser that parses identically but may have a more optimized
|
49
|
-
# structure.
|
50
|
-
#
|
51
|
-
# @return a parser that parses identically but may have a more optimized
|
52
|
-
# structure
|
53
|
-
def optimized
|
54
|
-
Skip[child.skip_optimized]
|
45
|
+
child.with_ws(ws).skip
|
55
46
|
end
|
56
|
-
|
57
|
-
# @
|
58
|
-
def
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
# @private
|
63
|
-
def skip_optimized #:nodoc:
|
64
|
-
child.skip_optimized
|
47
|
+
|
48
|
+
# @return (see Parser#skip)
|
49
|
+
def skip
|
50
|
+
self
|
65
51
|
end
|
66
|
-
|
52
|
+
|
67
53
|
end
|
68
54
|
end
|
@@ -14,38 +14,23 @@ module Rattler::Parsers
|
|
14
14
|
# @author Jason Arhart
|
15
15
|
#
|
16
16
|
class Token < Parser
|
17
|
-
|
17
|
+
|
18
18
|
# If the decorated parser matches return the entire matched string,
|
19
19
|
# otherwise return a false value.
|
20
20
|
#
|
21
21
|
# @param (see Parser#parse_labeled)
|
22
22
|
#
|
23
23
|
# @return (see Match#parse)
|
24
|
-
def parse(scanner, rules,
|
24
|
+
def parse(scanner, rules, scope = {})
|
25
25
|
p = scanner.pos
|
26
|
-
child.parse(scanner, rules) && scanner.string[p...(scanner.pos)]
|
26
|
+
child.parse(scanner, rules, scope) && scanner.string[p...(scanner.pos)]
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
# @param (see Parser#with_ws)
|
30
30
|
# @return (see Parser#with_ws)
|
31
31
|
def with_ws(ws)
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
# @return (see Parser#optimized)
|
36
|
-
def optimized
|
37
|
-
Token[child.token_optimized]
|
32
|
+
ws.skip & self
|
38
33
|
end
|
39
|
-
|
40
|
-
# @private
|
41
|
-
def token_optimized #:nodoc:
|
42
|
-
child.token_optimized
|
43
|
-
end
|
44
|
-
|
45
|
-
# @private
|
46
|
-
def skip_optimized #:nodoc:
|
47
|
-
child.skip_optimized
|
48
|
-
end
|
49
|
-
|
34
|
+
|
50
35
|
end
|
51
36
|
end
|
@@ -15,7 +15,7 @@ module Rattler::Parsers
|
|
15
15
|
#
|
16
16
|
class ZeroOrMore < Parser
|
17
17
|
include Combining
|
18
|
-
|
18
|
+
|
19
19
|
# Parse using the decorated parser as many times as it succeeds. Return the
|
20
20
|
# results in an array, or +true+ if the decorated parser is not
|
21
21
|
# <tt>capturing?</tt>.
|
@@ -23,38 +23,18 @@ module Rattler::Parsers
|
|
23
23
|
# @param (see Parser#parse_labeled)
|
24
24
|
#
|
25
25
|
# @return [Array, true] an array containing the decorated parser's parse
|
26
|
-
#
|
27
|
-
def parse(scanner, rules,
|
26
|
+
# results, or +true+ if the decorated parser is not <tt>capturing?</tt>
|
27
|
+
def parse(scanner, rules, scope = {})
|
28
28
|
a = []
|
29
|
-
while result = child.parse(scanner, rules)
|
29
|
+
while result = child.parse(scanner, rules, scope)
|
30
30
|
a << result
|
31
31
|
end
|
32
32
|
capturing? ? a : true
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def variable_capture_count?
|
36
36
|
true
|
37
37
|
end
|
38
|
-
|
39
|
-
# @private
|
40
|
-
def token_optimized #:nodoc:
|
41
|
-
to = super
|
42
|
-
if Match === to.child
|
43
|
-
to.child.re_zero_or_more
|
44
|
-
else
|
45
|
-
to
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# @private
|
50
|
-
def skip_optimized #:nodoc:
|
51
|
-
so = super
|
52
|
-
if Match === so.child
|
53
|
-
so.child.re_zero_or_more
|
54
|
-
else
|
55
|
-
so
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
38
|
+
|
59
39
|
end
|
60
40
|
end
|