From b274828831fec26cd8b3089ffef14cb96ce2de2f Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Thu, 16 Mar 2023 20:36:03 +1300 Subject: Second rewrite attempt, this one should work, monkaS --- src/__OLD_parcom/parser.cr | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/__OLD_parcom/parser.cr (limited to 'src/__OLD_parcom/parser.cr') diff --git a/src/__OLD_parcom/parser.cr b/src/__OLD_parcom/parser.cr new file mode 100644 index 0000000..ca350df --- /dev/null +++ b/src/__OLD_parcom/parser.cr @@ -0,0 +1,87 @@ +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 + + # Constructs an `Assert` parser with `self` and the given block. + def assert(&block : V -> Bool) : Assert(T, V) + Assert.new(self, &block) + end + + # 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 + end +end + -- cgit v1.2.1