module Drudge::Parsers::Primitives::Parser
This modules contains the parser combinators
Public Instance Methods
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
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
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
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
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
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
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
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
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
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
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
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
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
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
# 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