Class: Rattler::Parsers::Repeat

Inherits:
Parser show all
Includes:
Combining
Defined in:
lib/rattler/parsers/repeat.rb

Overview

Repeat decorates a parser with repeat counts to match repeatedly (up to the upper bound, if given) and succeed if the decorated parser succeeds at least as many times as specified by the lower bound.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Combining

#capturing?, #capturing_decidable?, #semantic?, #with_ws

Methods inherited from Parser

#&, #>>, #capturing?, #capturing_decidable?, #labeled?, #list, #one_or_more, #optional, #repeat, #semantic?, #sequence?, #skip, #with_ws, #zero_or_more, #|

Methods included from Runtime::ParserHelper

#select_captures

Methods inherited from Util::Node

#==, #[], #attrs, #can_equal?, #child, #children, #each, #empty?, #eql?, #initialize, #inspect, #method_missing, #name, #pretty_print, #pretty_print_cycle, #respond_to?, #same_contents?, #to_graphviz, #with_attrs, #with_attrs!, #with_children

Constructor Details

This class inherits a constructor from Rattler::Util::Node

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Rattler::Util::Node

Class Method Details

.[](parser, lower_bound, upper_bound = nil) ⇒ Repeat

Returns a parser that decorates parser and matches repeatedly.

Parameters:

  • parser (Parser)

    the parser to wrap and match with repeatedly

  • lower_bound (Integer)

    the minimum number of times to match

  • upper_bound (Integer) (defaults to: nil)

    the maximum number of times to match

Returns:

  • (Repeat)

    a parser that decorates parser and matches repeatedly



15
16
17
# File 'lib/rattler/parsers/repeat.rb', line 15

def self.[](parser, lower_bound, upper_bound = nil)
  self.new(parser, :lower_bound => lower_bound, :upper_bound => upper_bound)
end

.parsed(results, *_) ⇒ Object



20
21
22
23
# File 'lib/rattler/parsers/repeat.rb', line 20

def self.parsed(results, *_) #:nodoc
  parser, bounds = results
  self[parser, *bounds]
end

Instance Method Details

#lower_bound?Boolean

Returns true if there is a lower bound.

Returns:

  • (Boolean)

    true if there is a lower bound



68
69
70
# File 'lib/rattler/parsers/repeat.rb', line 68

def lower_bound?
  lower_bound > 0
end

#one_or_more?Boolean

Returns true if the bounds define a one-or-more parser.

Returns:

  • (Boolean)

    true if the bounds define a one-or-more parser



58
59
60
# File 'lib/rattler/parsers/repeat.rb', line 58

def one_or_more?
  lower_bound == 1 and not upper_bound?
end

#optional?Boolean

Returns true if the bounds define an optional (zero-or-one) parser.

Returns:

  • (Boolean)

    true if the bounds define an optional (zero-or-one) parser



63
64
65
# File 'lib/rattler/parsers/repeat.rb', line 63

def optional?
  lower_bound == 0 and upper_bound == 1
end

#parse(scanner, rules, scope = ParserScope.empty) ⇒ Array, Boolean

Parse using the wrapped parser repeatedly until it fails or the upper bound is reached. If the wrapped parser succeeds at least as many times as specified by the lower bound, return the results in an array, or true if the wrapped parser is not capturing?. Return false if the lower bound is not reached.

Parameters:

  • scanner (StringScanner)

    the scanner for the current parse

  • rules (RuleSet)

    the grammar rules being used for the current parse

  • scope (ParserScope) (defaults to: ParserScope.empty)

    the scope of captured results

Returns:

  • (Array, Boolean)

    an array containing the decorated parser’s parse results, or true if the decorated parser is not capturing?, or false if the decorated parser does not succeed up to the lower bound.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rattler/parsers/repeat.rb', line 37

def parse(scanner, rules, scope = ParserScope.empty)
  a = []
  start_pos = scanner.pos
  while result = child.parse(scanner, rules, scope)
    a << result
    break if upper_bound? and a.size >= upper_bound
  end
  if a.size >= lower_bound
    capturing? ? select_captures(a) : true
  else
    scanner.pos = start_pos
    false
  end
end

#upper_bound?Boolean

Returns true if there is an upper bound.

Returns:

  • (Boolean)

    true if there is an upper bound



73
74
75
# File 'lib/rattler/parsers/repeat.rb', line 73

def upper_bound?
  not upper_bound.nil?
end

#variable_capture_count?Boolean

Returns true if the number of parse results returned by the parser varies based on the input.

Returns:

  • (Boolean)

    true if the number of parse results returned by the parser varies based on the input



78
79
80
# File 'lib/rattler/parsers/repeat.rb', line 78

def variable_capture_count?
  true
end

#zero_or_more?Boolean

Returns true if the bounds define a zero-or-more.

Returns:

  • (Boolean)

    true if the bounds define a zero-or-more



53
54
55
# File 'lib/rattler/parsers/repeat.rb', line 53

def zero_or_more?
  lower_bound == 0 and not upper_bound?
end