aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parcom/parser.cr45
1 files changed, 41 insertions, 4 deletions
diff --git a/src/parcom/parser.cr b/src/parcom/parser.cr
index d74cbf8..ca350df 100644
--- a/src/parcom/parser.cr
+++ b/src/parcom/parser.cr
@@ -1,47 +1,84 @@
require "../parcom.cr"
module Parcom
+ # `Parser` is the base class of all parser objects and contains
+ # a handful of helper methods that can allow for cleaner syntax.
+ #
+ # The generic type `T` represents the type of tokens a parser will
+ # operate on (usually `Char`).
+ # The generic type `V` represents the type of value that a parser
+ # will return when parsing is successful.
abstract class Parser(T, V)
+ # Accepts a `Tokens(T)` and either retuns a `Result(T, V)`, or raises a
+ # `ParserFail` exception with a message providing context of where
+ # in the chain the parsing failed.
+ #
+ # The `V` in the returned `Result` is arbitrary, but the `Tokens(T)` in
+ # the returned result MUST contain the parser's input, with some tokens
+ # removed from the front proprtional to what was parsed.
+ #
+ # Example:
+ # ```
+ # hello = ParsesHello.new # inherits from Parser(Char, String)
+ # input = Tokens.from_string("Hello world!")
+ #
+ # result = hello.parse(input)
+ # result.value # => "Hello"
+ # result.tokens # => [' ', 'w', 'o', 'r', 'l', 'd', '!']
+ #
+ # bad_input = Tokens.from_string("Good evening world!")
+ # hello.parse(bad_input) # raises ParserFail
+ # ```
abstract def parse(tokens : Tokens(T)) : Result(T, V)
+ # Same as `#parse`, but returns `nil` instead of raising `ParserFail`.
def parse?(tokens : Tokens(T)) : Result(T, V)?
self.parse(tokens)
rescue ParserFail
return nil
end
+ # Constructs an `Alt` parser with `self` and `other`.
def |(other : Parser(T, V)) : Alt(T, V)
Alt.new(self, other)
end
+ # Constructs a `Plus` parser with `self` and `other`.
def +(other : Parser(T, U)) : Plus(T, V, U) forall U
Plus.new(self, other)
end
+ # Constructs a `Left` parser with `self` and `other`.
def <<(other : Parser(T, U)) : Left(T, V, U) forall U
Left.new(self, other)
end
+ # Constructs a `Right` parser with `self` and `other`.
def >>(other : Parser(T, U)) : Right(T, V, U) forall U
Right.new(self, other)
end
- def assert(f : V -> Bool)
- Assert.new(self, &f)
+ # Constructs an `Assert` parser with `self` and the given block.
+ def assert(&block : V -> Bool) : Assert(T, V)
+ Assert.new(self, &block)
end
- def assert(&block : V -> Bool)
- Assert.new(self, &block)
+ # Constructs an `Assert` parser with `self` and the given proc.
+ def assert(f : V -> Bool) : Assert(T, V)
+ Assert.new(self, &f)
end
+ # Constructs a `Map` parser with `self` and the given block.
def map(&block : V -> U) : Map(T, V, U) forall U
Map.new(self, &block)
end
+ # Constructs a `Map` parser with `self` and the given proc.
def map(f : V -> U) : Map(T, V, U) forall U
Map.new(self, &f)
end
+ # Constructs a `Recover` parser with `self` and the given `V`.
def recover(default : V) : Recover(T, V)
Recover.new(self, default)
end