class Paco::Parser

Attributes

desc[R]

Public Class Methods

new(desc = "", &block) click to toggle source

@param [String] desc

# File lib/paco/parser.rb, line 10
def initialize(desc = "", &block)
  @desc = desc
  @block = block
end

Public Instance Methods

<(other)
Alias for: skip
>(other)
Alias for: next
_parse(ctx) click to toggle source

@param [Paco::Context] ctx

# File lib/paco/parser.rb, line 30
def _parse(ctx)
  ctx.start_parse(self)
  res = @block.call(ctx, self)
  ctx.success_parse(res, self)
  res
end
at_least(num) click to toggle source

Returns a parser that runs ‘parser` at least `num` times, and returns an array of the results.

# File lib/paco/parser.rb, line 168
def at_least(num)
  Paco::Combinators.seq(times(num), many) do |head, rest|
    head + rest
  end
end
at_most(num) click to toggle source

Returns a parser that runs ‘parser` at most `num` times, and returns an array of the results.

# File lib/paco/parser.rb, line 176
def at_most(num)
  times(0, num)
end
bind(&block) click to toggle source

Returns a new parser which tries ‘parser`, and on success calls the `block` with the result of the parse, which is expected to return another parser, which will be tried next. This allows you to dynamically decide how to continue the parse, which is impossible with the other Paco::Combinators. @return [Paco::Parser]

# File lib/paco/parser.rb, line 88
def bind(&block)
  Parser.new("#{desc}.bind") do |ctx|
    block.call(_parse(ctx))._parse(ctx)
  end
end
Also aliased as: chain
chain(&block)
Alias for: bind
failure(ctx) click to toggle source

Raises ParseError @param [Paco::Context] ctx @raise [Paco::ParseError]

# File lib/paco/parser.rb, line 40
def failure(ctx)
  ctx.failure_parse(self)
  raise ParseError.new(ctx, desc), "", []
end
fallback(value) click to toggle source

Returns a new parser which tries ‘parser` and, if it fails, returns `value` without consuming any input. @return [Paco::Parser]

# File lib/paco/parser.rb, line 109
def fallback(value)
  self.or(Paco::Combinators.succeed(value))
end
fmap(&block) click to toggle source

Transforms the output of ‘parser` with the given block. @return [Paco::Parser]

# File lib/paco/parser.rb, line 76
def fmap(&block)
  Parser.new("#{desc}.fmap") do |ctx|
    block.call(_parse(ctx))
  end
end
join(separator = "") click to toggle source

Returns a parser that runs ‘parser` and concatenate it results with the `separator`. @param [String] separator @return [Paco::Parser]

# File lib/paco/parser.rb, line 139
def join(separator = "")
  fmap { |result| result.join(separator) }
end
many() click to toggle source

Expects ‘parser` zero or more times, and returns an array of the results. @return [Paco::Parser]

# File lib/paco/parser.rb, line 97
def many
  Paco::Combinators.many(self)
end
next(other) click to toggle source

Expects ‘other` parser to follow `parser`, but returns only the value of `other` parser. @param [Poco::Parser] other @return [Paco::Parser]

# File lib/paco/parser.rb, line 68
def next(other)
  Paco::Combinators.seq(self, other).fmap { |results| results[1] }
    .with_desc("#{desc}.next(#{other.desc})")
end
Also aliased as: >
not_followed_by(other) click to toggle source

Returns a parser that runs passed ‘other` parser without consuming the input, and returns result of the `parser` if the passed one _does not match_ the input. Fails otherwise. @param [Paco::Parser] other @return [Paco::Parser]

# File lib/paco/parser.rb, line 132
def not_followed_by(other)
  skip(Paco::Combinators.not_followed_by(other))
end
or(other) click to toggle source

Returns a new parser which tries ‘parser`, and if it fails uses `other`. @param [Paco::Parser] other @return [Paco::Parser]

# File lib/paco/parser.rb, line 48
def or(other)
  Parser.new("or(#{desc}, #{other.desc})") do |ctx|
    _parse(ctx)
  rescue ParseError
    other._parse(ctx)
  end
end
Also aliased as: |
parse(input, with_callstack: false) click to toggle source

@param [String, Paco::Context] input @param [true, false] with_callstack

# File lib/paco/parser.rb, line 24
def parse(input, with_callstack: false)
  ctx = input.is_a?(Context) ? input : Context.new(input, with_callstack: with_callstack)
  skip(Paco::Combinators.eof)._parse(ctx)
end
result(value) click to toggle source

Returns a new parser with the same behavior, but which returns passed ‘value`. @return [Paco::Parser]

# File lib/paco/parser.rb, line 103
def result(value)
  fmap { value }
end
skip(other) click to toggle source

Expects ‘other` parser to follow `parser`, but returns only the value of `parser`. @param [Poco::Parser] other @return [Paco::Parser]

# File lib/paco/parser.rb, line 60
def skip(other)
  Paco::Combinators.seq(self, other).fmap { |results| results[0] }.with_desc("#{desc}.skip(#{other.desc})")
end
Also aliased as: <
times(min, max = nil) click to toggle source

Returns a parser that runs ‘parser` between `min` and `max` times, and returns an array of the results. When `max` is not specified, `max` = `min`. @param [Integer] min @param [Integer] max @return [Paco::Parser]

# File lib/paco/parser.rb, line 148
def times(min, max = nil)
  max ||= min
  if min < 0 || max < min
    raise ArgumentError, "invalid attributes: min `#{min}`, max `#{max}`"
  end

  Parser.new("#{desc}.times(#{min}, #{max})") do |ctx|
    results = min.times.map { _parse(ctx) }
    (max - min).times.each do
      results << _parse(ctx)
    rescue ParseError
      break
    end

    results
  end
end
trim(other) click to toggle source

Expects ‘other` parser before and after `parser`, and returns the result of the parser. @param [Paco::Parser] other @return [Paco::Parser]

# File lib/paco/parser.rb, line 116
def trim(other)
  other.next(self).skip(other)
end
with_desc(desc) click to toggle source

@param [String] desc @return [Paco::Parser]

# File lib/paco/parser.rb, line 17
def with_desc(desc)
  @desc = desc
  self
end
wrap(before, after) click to toggle source

Expects the parser ‘before` before `parser` and `after` after `parser. Returns the result of the parser. @param [Paco::Parser] before @param [Paco::Parser] after @return [Paco::Parser]

# File lib/paco/parser.rb, line 124
def wrap(before, after)
  Paco::Combinators.wrap(before, after, self)
end
|(other)
Alias for: or