require "./parser.cr" require "./eof.cr" require "./map.cr" module Parcom # `Phrase` is a `Parser` that tries to parse with another parser, # but will fail if any of the input has not been consumed. # # Example: # ``` # letter_a = Token.new('a') # tokens = Tokens.from_string("aaa") # one_a = Phrase(Char, Char).new(letter_a) # result = one_a.parse(tokens) # This fails # ``` class Phrase(T, V) < Parser(T, V) @p : Map(T, {V, Nil}, V) # Accepts the parser to parse with. def initialize(p : Parser(T, V)) @p = (p + EOF(T).new).map &.first end # Tries to parse with the given parser, fails if there # is any un-parsed input remaining. def parse(tokens : Tokens(T)) : Result(T, V) @p.parse(tokens) rescue ex : ParserFail raise ParserFail.new("Phrase: #{ex.message}") end end end