diff options
| author | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-17 22:50:14 +1300 |
|---|---|---|
| committer | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-17 22:50:14 +1300 |
| commit | 982d239252b54297ff3558894038871f8d3a4175 (patch) | |
| tree | 41ab6073fd601caf2da0bf87c4cd8226b87b7126 /src/parcom.cr | |
| parent | f023ca56dbf9372464afe0060270fcef85271db0 (diff) | |
Please work this time
Diffstat (limited to 'src/parcom.cr')
| -rw-r--r-- | src/parcom.cr | 83 |
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 |
