class Paco::Parser
Attributes
Public Class Methods
@param [String] desc
# File lib/paco/parser.rb, line 10 def initialize(desc = "", &block) @desc = desc @block = block end
Public Instance Methods
@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
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
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
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
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
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
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
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
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
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
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
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
@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
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
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
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
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
@param [String] desc @return [Paco::Parser]
# File lib/paco/parser.rb, line 17 def with_desc(desc) @desc = desc self end
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