diff options
| -rw-r--r-- | src/parcom.cr | 2 | ||||
| -rw-r--r-- | src/parcom/phrase.cr | 33 |
2 files changed, 34 insertions, 1 deletions
diff --git a/src/parcom.cr b/src/parcom.cr index aa7abba..6c17596 100644 --- a/src/parcom.cr +++ b/src/parcom.cr @@ -81,7 +81,7 @@ module Parcom end end - class Phrase(T, V) + class Phrase(T, V) < Parser(T, V) @p : Map(T, {V, Nil}, V) def initialize(p : Parser(T, V)) diff --git a/src/parcom/phrase.cr b/src/parcom/phrase.cr new file mode 100644 index 0000000..1996fd4 --- /dev/null +++ b/src/parcom/phrase.cr @@ -0,0 +1,33 @@ +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 + |
