Class: Walrat::ParsletRepetition

Inherits:
ParsletCombination show all
Defined in:
lib/walrat/parslet_repetition.rb

Direct Known Subclasses

ParsletRepetitionDefault

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from ParsletCombination

#to_parseable

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(parseable, min, max = nil) ⇒ ParsletRepetition

Raises an ArgumentError if parseable or min is nil.

Raises:

  • (ArgumentError)


30
31
32
33
34
35
36
# File 'lib/walrat/parslet_repetition.rb', line 30

def initialize parseable, min, max = nil
  raise ArgumentError, 'nil parseable' if parseable.nil?
  raise ArgumentError, 'nil min' if min.nil?
  @parseable = parseable
  self.min = min
  self.max = max
end

Instance Attribute Details

#hashObject (readonly)

Returns the value of attribute hash.



27
28
29
# File 'lib/walrat/parslet_repetition.rb', line 27

def hash
  @hash
end

Instance Method Details

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
84
85
86
# File 'lib/walrat/parslet_repetition.rb', line 81

def eql?(other)
  other.instance_of? ParsletRepetition and
    @min == other.min and
    @max == other.max and
    @parseable.eql? other.parseable
end

#parse(string, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/walrat/parslet_repetition.rb', line 38

def parse string, options = {}
  raise ArgumentError, 'nil string' if string.nil?
  state = ParserState.new string, options
  catch :ZeroWidthParseSuccess do             # a zero-width match is grounds for immediate abort
    while @max.nil? or state.length < @max    # try forever if max is nil; otherwise keep trying while match count < max
      begin
        parsed = @parseable.memoizing_parse state.remainder, state.options
        state.parsed parsed
      rescue SkippedSubstringException => e
        state.skipped e
      rescue ParseError => e # failed, will try to skip; save original error in case skipping fails
        if options.has_key?(:skipping_override)
          skipping_parslet = options[:skipping_override]
        elsif options.has_key?(:skipping)
          skipping_parslet = options[:skipping]
        else
          skipping_parslet = nil
        end
        break if skipping_parslet.nil?
        begin
          # guard against self references (possible infinite recursion) here?
          parsed = skipping_parslet.memoizing_parse state.remainder, state.options
          state.skipped parsed
          redo  # skipping succeeded, try to redo
        rescue ParseError
          break # skipping didn't help either, give up
        end
      end
    end
  end

  # now assess whether our tries met the requirements
  if state.length == 0 and @min == 0 # success (special case)
    throw :ZeroWidthParseSuccess
  elsif state.length < @min          # matches < min (failure)
    raise ParseError.new('required %d matches but obtained %d while parsing "%s"' % [@min, state.length, string],
                         :line_end    => state.options[:line_end],
                         :column_end  => state.options[:column_end])
  else                              # success (general case)
    state.results                   # returns multiple matches as an array, single matches as a single object
  end
end