module Drudge::Parsers::Primitives::Parser

This modules contains the parser combinators

Public Instance Methods

<=(other) click to toggle source

sequencing: same as ‘>’ but returns only the result of self, disregarding the result of the other

# File lib/drudge/parsers/primitives.rb, line 163
def <=(other)
  (self > other.discard)
end
>(other) click to toggle source

sequening: returns a parser that succeeds if self succeeds, follwing by the otheer parser on the remaining input returns a Tuple of both results

# File lib/drudge/parsers/primitives.rb, line 147
def >(other)
  self.flat_map do |result1|
    other.map do |result2|
      result1 + result2
    end
  end.describe("#{self.to_s} #{other.to_s}")
end
>=(other) click to toggle source

sequencing: same as ‘>’ but returns only the result of the other parser, discarding the result of the first

# File lib/drudge/parsers/primitives.rb, line 157
def >=(other)
  (self.discard > other)
end
describe(str) click to toggle source

attach a description to the parser

# File lib/drudge/parsers/primitives.rb, line 254
def describe(str)
  self.define_singleton_method(:to_s) do
    str
  end

  self
end
discard() click to toggle source

Returns a parser that, if self is successful will dicard its result Used in combination with sequencing to achieve lookahead / lookbehind

# File lib/drudge/parsers/primitives.rb, line 132
def discard
  parser do |input|
    result = self[input]

    if Success === result
      Success(Empty(), result.remaining)
    else
      result
    end
  end.describe(self.to_s)
end
flat_map(&f) click to toggle source

monadic bind (or flat map) for a parser f should take the result of the current parser and return a the parser that will consume the next input. Used for sequencing

# File lib/drudge/parsers/primitives.rb, line 124
def flat_map(&f)
  parser do |input|
    self[input].flat_map_with_next &f
  end
end
map(&f) click to toggle source

Returns a new parser that applies the parser function to the parse result of self

# File lib/drudge/parsers/primitives.rb, line 100
def map(&f)
  parser { |input| f[self[input]] }.describe(self.to_s)
end
map_in_parse_result(&f) click to toggle source

likemap but yields the the contents of the ParseResult instead of the vrapped value

# File lib/drudge/parsers/primitives.rb, line 115
def map_in_parse_result(&f)
  parser { |input| self[input].map &f }.describe(self.to_s)
end
Also aliased as: mapr
map_in_parse_value(&f) click to toggle source

like map but yields the actual value of the parse result (ParseResult contains ParseValue which contains the actual value) wrapped value. Usefull if you want to know if the result was a sequence or not

# File lib/drudge/parsers/primitives.rb, line 108
def map_in_parse_value(&f)
  parser { |input| self[input].map { |pr| pr.map &f } }.describe(self.to_s)
end
Also aliased as: mapv
mapr(&f)
Alias for: map_in_parse_result
mapv(&f)
Alias for: map_in_parse_value
optional() click to toggle source

makes this parser opitonal

# File lib/drudge/parsers/primitives.rb, line 192
def optional
  self.map do |parse_result|
    case parse_result
    when Success
      parse_result
    else
      Success(Empty(), parse_result.remaining)
    end
  end.describe("[#{self.to_s}]")
end
reject() click to toggle source

creates a parser that will reject a whatever this parser succeeds in parsing if this parser fails, the ‘rejected’ version will succeed with Empty() nad will not consume any input

# File lib/drudge/parsers/primitives.rb, line 206
def reject
  parser do |input|
    result = self[input]

    if result.success?
      Failure("Unexpected #{self.to_s}", result.remaining)
    else
      Success(Empty(), input)
    end
  end.describe("!#{self.to_s}")
end
repeats(kind = :*, till: self.reject | eos("eos")) click to toggle source

returns a parser that repeatedly parses with self until it fails

# File lib/drudge/parsers/primitives.rb, line 220
def repeats(kind = :*, till: self.reject | eos("eos"))

  case kind
  when :* then (rep1(till: till) | success(Empty())).describe("[#{self} ...]")
  when :+ then rep1(till: till).describe( "#{self} [#{self} ...]")
  else raise "Unknown repetition kind for #{self}"
  end
end
with_failure_message(&failure_converter) click to toggle source

converts the failure message

# File lib/drudge/parsers/primitives.rb, line 263
def with_failure_message(&failure_converter) 
  parser do |input|
    result = self[input]

    case result
    when Success
      result
    when Failure
      Failure(failure_converter[result.message, input], result.remaining)
    end
  end.describe self.to_s
end
|(other) click to toggle source

alternation: try this parser and if it fails (but not with an Error) try the other parser

# File lib/drudge/parsers/primitives.rb, line 169
def |(other)
  parser do |input|
    result1 = self[input]

    case result1
    when Success
      result1
    when Failure
      result2 = other[input]

      # return the failure that happened earlier in the stream
      if Failure == result2 && result1.remaining.count > result2.remaining.count
        result1
      else
        result2
      end
    when Error
      result1
    end
  end.describe("#{self.to_s} | #{other.to_s}")
end

Private Instance Methods

rep1(till: self.reject) click to toggle source
# File lib/drudge/parsers/primitives.rb, line 230
def rep1(till: self.reject)
  parser do |input|
    results = self[input]
    remaining = results.remaining

    if results.success?
      while results.success? && !till[remaining].success?
        results += self[remaining]
        remaining = results.remaining
      end
    end

    till_result = till[remaining]
    if till_result.success?
      results
    else
      till_result
    end
  end
end