Class: Walrat::ParsletChoice
- Inherits:
-
ParsletCombination
- Object
- ParsletCombination
- Walrat::ParsletChoice
- Defined in:
- lib/walrat/parslet_choice.rb
Instance Attribute Summary collapse
-
#hash ⇒ Object
readonly
Returns the value of attribute hash.
Instance Method Summary collapse
- #eql?(other) ⇒ Boolean
-
#initialize(left, right, *others) ⇒ ParsletChoice
constructor
Either parameter may be a Parslet or a ParsletCombination.
-
#parse(string, options = {}) ⇒ Object
First tries to parse the left option, falling back and trying the right option and then the any subsequent options in the others instance variable on failure.
-
#|(next_parslet) ⇒ Object
Override so that alternatives are appended to an existing sequence: Consider the following example:.
Methods inherited from ParsletCombination
Methods included from Memoizing
#check_left_recursion, #memoizing_parse
Methods included from ParsletCombining
#&, #>>, #and?, #and_predicate, #choice, #memoizing_parse, #merge, #not!, #not_predicate, #omission, #one_or_more, #optional, #repeat, #repeat_with_default, #repetition, #repetition_with_default, #sequence, #skip, #zero_or_more, #zero_or_one
Constructor Details
#initialize(left, right, *others) ⇒ ParsletChoice
Either parameter may be a Parslet or a ParsletCombination. Neither parmeter may be nil.
31 32 33 34 35 36 |
# File 'lib/walrat/parslet_choice.rb', line 31 def initialize left, right, *others raise ArgumentError if left.nil? raise ArgumentError if right.nil? @alternatives = [left, right] + others update_hash end |
Instance Attribute Details
#hash ⇒ Object (readonly)
Returns the value of attribute hash.
27 28 29 |
# File 'lib/walrat/parslet_choice.rb', line 27 def hash @hash end |
Instance Method Details
#eql?(other) ⇒ Boolean
120 121 122 123 124 125 126 127 128 |
# File 'lib/walrat/parslet_choice.rb', line 120 def eql? other return false if not other.instance_of? ParsletChoice other_alternatives = other.alternatives return false if @alternatives.length != other_alternatives.length for i in 0..(@alternatives.length - 1) return false unless @alternatives[i].eql? other_alternatives[i] end true end |
#parse(string, options = {}) ⇒ Object
First tries to parse the left option, falling back and trying the right option and then the any subsequent options in the others instance variable on failure. If no options successfully complete parsing then an ParseError is raised. Any zero-width parse successes thrown by alternative parsers will flow on to a higher level.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/walrat/parslet_choice.rb', line 71 def parse string, = {} raise ArgumentError if string.nil? error = nil # for error reporting purposes will track which parseable gets farthest to the right before failing left_recursion = nil # will also track any left recursion that we detect @alternatives.each do |parseable| begin result = parseable.memoizing_parse(string, ) # successful parse if left_recursion and left_recursion.continuation # and we have a continuation continuation = left_recursion.continuation # continuations are once-only, one-way tickets left_recursion = nil # set this to nil so as not to call it again without meaning to continuation.call(result) # so jump back to where we were before end return result rescue LeftRecursionException => e left_recursion = e # TODO: # it's not enough to just catch this kind of exception and remember # the last one # may need to accumulate these in an array # consider the example rule: # :a, :a & :b | :a & :c | :a & :d | :b # the first option will raise a LeftRecursionException # the next option will raise for the same reason # the third likewise # finally we get to the fourth option, the first which might succeed # at that point we should have three continuations # we should try the first, falling back to the second and third if # necessary # on successfully retrying, need to start all over again and try all # the options again, just in case further recursion is possible # so it is quite complicated # the question is, is it more complicated than the other ways of # getting right-associativity into Walrat-generated parsers? rescue ParseError => e if error.nil? error = e else error = e unless error.rightmost?(e) end end end # should generally report the rightmost error raise ParseError.new('no valid alternatives while parsing "%s" (%s)' % [string, error.to_s], :line_end => error.line_end, :column_end => error.column_end) end |
#|(next_parslet) ⇒ Object
Override so that alternatives are appended to an existing sequence: Consider the following example:
A | B
This constitutes a single choice:
(A | B)
If we then make this a three-element sequence:
A | B | C
We are effectively creating an nested sequence containing the original sequence and an additional element:
((A | B) | C)
Although such a nested sequence is correctly parsed it is not as architecturally clean as a single sequence without nesting:
(A | B | C)
This method allows us to use the architecturally cleaner format.
62 63 64 |
# File 'lib/walrat/parslet_choice.rb', line 62 def |(next_parslet) append next_parslet end |