aboutsummaryrefslogtreecommitdiff
path: root/src/parcom.cr
diff options
context:
space:
mode:
Diffstat (limited to 'src/parcom.cr')
-rw-r--r--src/parcom.cr83
1 files changed, 0 insertions, 83 deletions
diff --git a/src/parcom.cr b/src/parcom.cr
index ffa5654..8387752 100644
--- a/src/parcom.cr
+++ b/src/parcom.cr
@@ -77,88 +77,5 @@ module Parcom
map(block)
end
end
-
- # A parser defines a process of extracting some sort of data
- # from a stream of tokens.
- # `Parser` objects wrap a function/block that accepts a `Tokens` object,
- # and either returns a `Result`, or raises a `ParserFail`.
- # This struct also defines a handful of methods for modifying a parser's
- # behavior.
- #
- # The function that is wrapped by a parser should:
- # 1. Have the type `Tokens(T) -> Result(T, U)`
- # 1. Indicate failure by raising a `ParserFail`
- # 1. Not introduce side-effects
- #
- # Instead of inheriting from `Parser`, custom parsers should be
- # defined using a method that generates the parser directly:
- # ```
- # struct Foo(T, U) < Parser(T, Array(U))
- # def parse(tokens)
- # # This will cause headaches
- # end
- # end
- #
- # # Do this instead:
- # def foo(t : T.class, u : U.class, p : Parser(T, U)) : Parser(T, U) forall T, U
- # Parser(T, U).new("Foo") { |tokens| "your code here" }
- # end
- # ```
- struct Parser(T, U)
- getter name
-
- def initialize(@name : String, @f : Tokens(T) -> Result(T, U))
- end
-
- def initialize(@name : String, &block : Tokens(T) -> Result(T, U))
- @f = block
- end
-
- # Changes the `name` property and returns `self`.
- # This should be used to specify a custom name:
- # ```
- # a = Basic.token(Char, 'a').named("letter a")
- # ```
- def named(name : String) : self
- @name = name
- self
- end
-
- def parse(tokens : Tokens(T)) : Result(T, U)
- @f.call(tokens)
- end
-
- def parse?(tokens : Tokens(T)) : Result(T, U)?
- parse(tokens)
- rescue
- nil
- end
-
- def assert(f : U -> Bool) : Parser(T, U)
- p = self
- Parser.new("#{p.name} (assertion)") do |tokens|
- result = p.parse(tokens)
- unless f.call(r.value)
- raise ParserFail.new("Assertion failed for value #{r.value}")
- end
- result
- end
- end
-
- def assert(&block : U -> Bool) : Parser(T, U)
- assert(block)
- end
-
- def map(f : U -> T) : Parser(T, V) forall V
- p = self
- Parser(T, V).new("#{p.name} (mapped)") do |tokens|
- p.parse(tokens).map(f)
- end
- end
-
- def map(&block : U -> T) : Parser(T, V) forall V
- map(block)
- end
- end
end