rattler 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/rattler/parsers/list.rb
CHANGED
@@ -15,41 +15,10 @@ module Rattler::Parsers
|
|
15
15
|
#
|
16
16
|
# @author Jason Arhart
|
17
17
|
#
|
18
|
-
class List <
|
19
|
-
|
18
|
+
class List < ListParser
|
19
|
+
protected
|
20
20
|
|
21
|
-
|
22
|
-
def self.parsed(results, *_) #:nodoc:
|
23
|
-
self[*results]
|
24
|
-
end
|
25
|
-
|
26
|
-
# Create a new list parser that matches terms with +term_parser+ and
|
27
|
-
# separators with +sep_parser+
|
28
|
-
def self.[](term_parser, sep_parser)
|
29
|
-
self.new(term_parser, :sep_parser => sep_parser)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Parse terms matched by the term parser in a list with separators matched
|
33
|
-
# by the separator parser. Return the terms in an array, or +true+ if the
|
34
|
-
# term parser is not <tt>capturing?</tt>.
|
35
|
-
#
|
36
|
-
# @param (see Parser#parse_labeled)
|
37
|
-
#
|
38
|
-
# @return [Array, true] an array containing the term parser's parse results,
|
39
|
-
# or +true+ if the term parser is not <tt>capturing?</tt>
|
40
|
-
def parse(scanner, rules, labeled = {})
|
41
|
-
a = []
|
42
|
-
p = scanner.pos
|
43
|
-
while result = child.parse(scanner, rules)
|
44
|
-
p = scanner.pos
|
45
|
-
a << result
|
46
|
-
break unless sep_parser.parse(scanner, rules)
|
47
|
-
end
|
48
|
-
scanner.pos = p
|
49
|
-
capturing? ? a : true
|
50
|
-
end
|
51
|
-
|
52
|
-
def variable_capture_count?
|
21
|
+
def enough?(results)
|
53
22
|
true
|
54
23
|
end
|
55
24
|
|
@@ -15,43 +15,11 @@ module Rattler::Parsers
|
|
15
15
|
#
|
16
16
|
# @author Jason Arhart
|
17
17
|
#
|
18
|
-
class List1 <
|
19
|
-
|
18
|
+
class List1 < ListParser
|
19
|
+
protected
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
self[*results]
|
24
|
-
end
|
25
|
-
|
26
|
-
# Create a new list1 parser that matches terms with +term_parser+ and
|
27
|
-
# separators with +sep_parser+
|
28
|
-
def self.[](term_parser, sep_parser)
|
29
|
-
self.new(term_parser, :sep_parser => sep_parser)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Parse terms matched by the term parser in a list with separators matched
|
33
|
-
# by the separator parser. Return the terms in an array, or +true+ if the
|
34
|
-
# term parser is not <tt>capturing?</tt>, or +false+ if no terms matched..
|
35
|
-
#
|
36
|
-
# @param (see Parser#parse_labeled)
|
37
|
-
#
|
38
|
-
# @return [Array, true] an array containing the term parser's parse results,
|
39
|
-
# or +true+ if the term parser is not <tt>capturing?</tt>, or +false+ if
|
40
|
-
# no terms matched.
|
41
|
-
def parse(scanner, rules, labeled = {})
|
42
|
-
a = []
|
43
|
-
p = scanner.pos
|
44
|
-
while result = child.parse(scanner, rules)
|
45
|
-
p = scanner.pos
|
46
|
-
a << result
|
47
|
-
break unless sep_parser.parse(scanner, rules)
|
48
|
-
end
|
49
|
-
scanner.pos = p
|
50
|
-
(capturing? ? a : true) unless a.empty?
|
51
|
-
end
|
52
|
-
|
53
|
-
def variable_capture_count?
|
54
|
-
true
|
21
|
+
def enough?(results)
|
22
|
+
not results.empty?
|
55
23
|
end
|
56
24
|
|
57
25
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/parsers/list.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rattler/parsers'
|
9
|
+
|
10
|
+
module Rattler::Parsers
|
11
|
+
#
|
12
|
+
# +ListParser+ matches terms matched by a term parser in a list with
|
13
|
+
# separators matched by a separator parser.
|
14
|
+
#
|
15
|
+
# @author Jason Arhart
|
16
|
+
#
|
17
|
+
class ListParser < Parser
|
18
|
+
include Combining
|
19
|
+
|
20
|
+
# @private
|
21
|
+
def self.parsed(results, *_) #:nodoc:
|
22
|
+
self[*results]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a new list parser that matches terms with +term_parser+ and
|
26
|
+
# separators with +sep_parser+
|
27
|
+
def self.[](term_parser, sep_parser)
|
28
|
+
self.new(term_parser, sep_parser.skip)
|
29
|
+
end
|
30
|
+
|
31
|
+
def term_parser
|
32
|
+
children[0]
|
33
|
+
end
|
34
|
+
|
35
|
+
def sep_parser
|
36
|
+
children[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Parse terms matched by the term parser in a list with separators matched
|
40
|
+
# by the separator parser. Return the terms in an array, or +true+ if the
|
41
|
+
# term parser is not <tt>capturing?</tt>.
|
42
|
+
#
|
43
|
+
# @param (see Parser#parse_labeled)
|
44
|
+
#
|
45
|
+
# @return [Array, true] an array containing the term parser's parse results,
|
46
|
+
# or +true+ if the term parser is not <tt>capturing?</tt>
|
47
|
+
def parse(scanner, rules, scope = {})
|
48
|
+
a = []
|
49
|
+
p = scanner.pos
|
50
|
+
while result = term_parser.parse(scanner, rules, scope)
|
51
|
+
p = scanner.pos
|
52
|
+
a << result
|
53
|
+
break unless sep_parser.parse(scanner, rules, scope)
|
54
|
+
end
|
55
|
+
scanner.pos = p
|
56
|
+
(capturing? ? a : true) if enough? a
|
57
|
+
end
|
58
|
+
|
59
|
+
def variable_capture_count?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -16,7 +16,7 @@ module Rattler::Parsers
|
|
16
16
|
# @author Jason Arhart
|
17
17
|
#
|
18
18
|
class Match < Parser
|
19
|
-
|
19
|
+
|
20
20
|
# Create a new parser that matches with +re+.
|
21
21
|
#
|
22
22
|
# @param [Regexp] re the pattern to match
|
@@ -26,62 +26,27 @@ module Rattler::Parsers
|
|
26
26
|
def self.[](re)
|
27
27
|
self.new(:re => re)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# @private
|
31
31
|
def self.parsed(results, *_) #:nodoc:
|
32
32
|
self[eval(results.first)]
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# If the +Regexp+ matches at the parse position, return the matched
|
36
36
|
# string, otherwise return a false value.
|
37
37
|
#
|
38
38
|
# @param (see Parser#parse_labeled)
|
39
39
|
#
|
40
40
|
# @return the matched string, or +nil+
|
41
|
-
def parse(scanner, rules,
|
41
|
+
def parse(scanner, rules, scope={})
|
42
42
|
scanner.scan re
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# @param (see Parser#with_ws)
|
46
46
|
# @return (see Parser#with_ws)
|
47
47
|
def with_ws(ws)
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
# @private
|
52
|
-
def re_optional #:nodoc:
|
53
|
-
Match[/#{atomic_re.source}?/]
|
54
|
-
end
|
55
|
-
|
56
|
-
# @private
|
57
|
-
def re_zero_or_more #:nodoc:
|
58
|
-
Match[/#{atomic_re.source}*/]
|
59
|
-
end
|
60
|
-
|
61
|
-
# @private
|
62
|
-
def re_one_or_more #:nodoc:
|
63
|
-
Match[/#{atomic_re.source}+/]
|
48
|
+
ws.skip & self
|
64
49
|
end
|
65
|
-
|
66
|
-
# @private
|
67
|
-
def assert_re #:nodoc:
|
68
|
-
/(?=#{re.source})/
|
69
|
-
end
|
70
|
-
|
71
|
-
# @private
|
72
|
-
def disallow_re #:nodoc:
|
73
|
-
/(?!#{re.source})/
|
74
|
-
end
|
75
|
-
|
76
|
-
# @private
|
77
|
-
def atomic_re #:nodoc:
|
78
|
-
/(?>#{re.source})/
|
79
|
-
end
|
80
|
-
|
81
|
-
# @private
|
82
|
-
def as_match #:nodoc:
|
83
|
-
self
|
84
|
-
end
|
85
|
-
|
50
|
+
|
86
51
|
end
|
87
52
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# = rattler/parsers/node_code.rb
|
3
|
+
#
|
4
|
+
# Author:: Jason Arhart
|
5
|
+
# Documentation:: Author
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rattler/parsers'
|
9
|
+
|
10
|
+
module Rattler::Parsers
|
11
|
+
# @private
|
12
|
+
class NodeCode #:nodoc:
|
13
|
+
|
14
|
+
def self.bindable_code(action)
|
15
|
+
self.new(action.target, action.method_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(target_name, method_name)
|
19
|
+
@target_name = target_name
|
20
|
+
@method_name = method_name
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :target_name, :method_name
|
24
|
+
|
25
|
+
def bind(scope, bind_args)
|
26
|
+
args = [array_expr(bind_args)]
|
27
|
+
if not scope.empty?
|
28
|
+
labeled = '{' + scope.map {|k, v| ":#{k} => #{v}"}.join(', ') + '}'
|
29
|
+
args << ":labeled => #{labeled}"
|
30
|
+
end
|
31
|
+
t = target_name == 'self' ? '' : "#{target_name}."
|
32
|
+
"#{t}#{method_name}(#{args.join ', '})"
|
33
|
+
end
|
34
|
+
|
35
|
+
def array_expr(bind_args)
|
36
|
+
if bind_args.respond_to? :to_str
|
37
|
+
bind_args
|
38
|
+
else
|
39
|
+
'[' + bind_args.join(', ') + ']'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -16,12 +16,12 @@ module Rattler::Parsers
|
|
16
16
|
#
|
17
17
|
class OneOrMore < Parser
|
18
18
|
include Combining
|
19
|
-
|
19
|
+
|
20
20
|
# Parse using the wrapped parser repeatedly until it fails. If the
|
21
21
|
# wrapped parser succeeds at least once return the results in an array,
|
22
22
|
# or +true+ if the wrapped parser is not <tt>capturing?</tt>. Return
|
23
23
|
# +false+ if the wrapped parser does not succeed at least once.
|
24
|
-
|
24
|
+
|
25
25
|
# Parse using the decorated parser as many times as it succeeds. If it does
|
26
26
|
# not succeeds at least once return +false+, otherwise the results in an
|
27
27
|
# array, or +true+ if the decorated parser is not <tt>capturing?</tt>.
|
@@ -29,39 +29,19 @@ module Rattler::Parsers
|
|
29
29
|
# @param (see Parser#parse_labeled)
|
30
30
|
#
|
31
31
|
# @return [Array, Boolean] an array containing the decorated parser's parse
|
32
|
-
#
|
32
|
+
# results, or +true+ if the decorated parser is not <tt>capturing?</tt>,
|
33
33
|
# or +false+ if the decorated parser does not succeed at least once.
|
34
|
-
def parse(scanner, rules,
|
34
|
+
def parse(scanner, rules, scope = {})
|
35
35
|
a = []
|
36
|
-
while result = child.parse(scanner, rules)
|
36
|
+
while result = child.parse(scanner, rules, scope)
|
37
37
|
a << result
|
38
38
|
end
|
39
39
|
(capturing? ? a : true) unless a.empty?
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def variable_capture_count?
|
43
43
|
true
|
44
44
|
end
|
45
|
-
|
46
|
-
# @private
|
47
|
-
def token_optimized #:nodoc:
|
48
|
-
to = super
|
49
|
-
if Match === to.child
|
50
|
-
to.child.re_one_or_more
|
51
|
-
else
|
52
|
-
to
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# @private
|
57
|
-
def skip_optimized #:nodoc:
|
58
|
-
to = super
|
59
|
-
if Match === to.child
|
60
|
-
to.child.re_one_or_more
|
61
|
-
else
|
62
|
-
to
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
45
|
+
|
66
46
|
end
|
67
47
|
end
|
@@ -15,7 +15,7 @@ module Rattler::Parsers
|
|
15
15
|
#
|
16
16
|
class Optional < Parser
|
17
17
|
include Combining
|
18
|
-
|
18
|
+
|
19
19
|
# Parse using the decorated parser and always succeed. If the decorated
|
20
20
|
# parser is <tt>capturing?</tt> return the result in an array, or an empty
|
21
21
|
# array if the wrapped parser fails. If the decorated parser is not
|
@@ -26,37 +26,17 @@ module Rattler::Parsers
|
|
26
26
|
# @return [Array, true] an array containing the decorated parser's parse
|
27
27
|
# results if it matches or an empty array if not, or always +true+ if the
|
28
28
|
# decorated parser is not <tt>capturing?</tt>
|
29
|
-
def parse(scanner, rules,
|
30
|
-
if result = child.parse(scanner, rules)
|
29
|
+
def parse(scanner, rules, scope = {})
|
30
|
+
if result = child.parse(scanner, rules, scope)
|
31
31
|
capturing? ? [result] : true
|
32
32
|
else
|
33
33
|
capturing? ? [] : true
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def variable_capture_count?
|
38
38
|
true
|
39
39
|
end
|
40
|
-
|
41
|
-
# @private
|
42
|
-
def token_optimized #:nodoc:
|
43
|
-
to = super
|
44
|
-
if Match === to.child
|
45
|
-
to.child.re_optional
|
46
|
-
else
|
47
|
-
to
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# @private
|
52
|
-
def skip_optimized #:nodoc:
|
53
|
-
so = super
|
54
|
-
if Match === so.child
|
55
|
-
so.child.re_optional
|
56
|
-
else
|
57
|
-
so
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
40
|
+
|
61
41
|
end
|
62
42
|
end
|
@@ -14,12 +14,12 @@ module Rattler::Parsers
|
|
14
14
|
# @author Jason Arhart
|
15
15
|
#
|
16
16
|
class Parser < Rattler::Util::Node
|
17
|
-
|
17
|
+
|
18
18
|
# @private
|
19
19
|
def self.parsed(*args) #:nodoc:
|
20
20
|
self[*args]
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# Return +true+ if the parser returns parse results on success, or
|
24
24
|
# +false+ if the parser simply returns +true+ on success.
|
25
25
|
#
|
@@ -28,11 +28,11 @@ module Rattler::Parsers
|
|
28
28
|
def capturing?
|
29
29
|
true
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def variable_capture_count?
|
33
33
|
false
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Return +true+ if the parser associates a label with parse results. Only
|
37
37
|
# instances of +Label+ should return +true+.
|
38
38
|
#
|
@@ -40,77 +40,49 @@ module Rattler::Parsers
|
|
40
40
|
def labeled?
|
41
41
|
false
|
42
42
|
end
|
43
|
-
|
44
|
-
# Parse and on success associate the label with the parse result if
|
45
|
-
# +labeled?+ and +capturing?+.
|
46
|
-
#
|
47
|
-
# @param [StringScanner] scanner the scanner used match patterns
|
48
|
-
# @param [Rules] rules the parse rules defining the parser
|
49
|
-
# @param [Hash] labeled a hash for associating labels with children
|
50
|
-
#
|
51
|
-
# @return the parse result on success, or a false value on failure
|
52
|
-
def parse_labeled(scanner, rules, labeled)
|
53
|
-
parse(scanner, rules, labeled)
|
54
|
-
end
|
55
|
-
|
43
|
+
|
56
44
|
# @param [Parser] other the parser to try if this parser fails.
|
57
45
|
# @return a new parser that tries this parser first and if it fails tries
|
58
46
|
# +other+
|
59
47
|
def |(other)
|
60
48
|
Choice[self, other]
|
61
49
|
end
|
62
|
-
|
50
|
+
|
63
51
|
# @param [Parser] other the next parser to try if this parser succeeds.
|
64
52
|
# @return a new parser that tries both this parser and +other+ and fails
|
65
53
|
# unless both parse in sequence
|
66
54
|
def &(other)
|
67
55
|
Sequence[self, other]
|
68
56
|
end
|
69
|
-
|
57
|
+
|
70
58
|
# @return a new parser that tries this parser but returns +true+ if it
|
71
59
|
# fails
|
72
60
|
def optional
|
73
61
|
Optional[self]
|
74
62
|
end
|
75
|
-
|
63
|
+
|
76
64
|
# @return a new parser that tries this parser until it fails and returns
|
77
65
|
# all of the results
|
78
66
|
def zero_or_more
|
79
67
|
ZeroOrMore[self]
|
80
68
|
end
|
81
|
-
|
69
|
+
|
82
70
|
# @return a new parser that tries this parser until it fails and returns
|
83
71
|
# all of the results if it succeeded at least once and fails otherwise
|
84
72
|
def one_or_more
|
85
73
|
OneOrMore[self]
|
86
74
|
end
|
87
|
-
|
75
|
+
|
76
|
+
# @return a new parser that skips over what this parser matches
|
77
|
+
def skip
|
78
|
+
Skip[self]
|
79
|
+
end
|
80
|
+
|
88
81
|
# @param [Parser] ws the parser used to skip whitespace
|
89
82
|
# @return [Parser] a new parser that uses +ws+ to skip whitespace
|
90
83
|
def with_ws(ws)
|
91
84
|
self
|
92
85
|
end
|
93
|
-
|
94
|
-
# @return [Parser] a parser that parses identically but may have a more
|
95
|
-
# optimized structure
|
96
|
-
def optimized
|
97
|
-
self
|
98
|
-
end
|
99
|
-
|
100
|
-
# @private
|
101
|
-
def token_optimized #:nodoc:
|
102
|
-
self
|
103
|
-
end
|
104
|
-
|
105
|
-
# @private
|
106
|
-
def skip_optimized #:nodoc:
|
107
|
-
self
|
108
|
-
end
|
109
|
-
|
110
|
-
# @private
|
111
|
-
def as_match #:nodoc:
|
112
|
-
nil
|
113
|
-
end
|
114
|
-
|
86
|
+
|
115
87
|
end
|
116
88
|
end
|