diff options
| author | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-09 21:32:35 +1300 |
|---|---|---|
| committer | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-09 21:32:35 +1300 |
| commit | a26ccb40ca98c82f486f1c57334ccc04534a1a23 (patch) | |
| tree | 4d44196022f2280ecc47e07802c6575c3df1ac1a /src | |
| parent | 9dc06838e3c78e4a77731cab6bc773846eafce99 (diff) | |
Implement between + improve error handling
Diffstat (limited to 'src')
| -rw-r--r-- | src/parcom.cr | 77 |
1 files changed, 68 insertions, 9 deletions
diff --git a/src/parcom.cr b/src/parcom.cr index 0a97e51..c1ac147 100644 --- a/src/parcom.cr +++ b/src/parcom.cr @@ -121,6 +121,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, V) result = @p.parse(tokens) Result.new(tokens, result.value) + rescue ex : ParserException + raise ParserException.new("Peek: #{ex.message}") end end @@ -131,18 +133,28 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, V) result = @p.parse(tokens) - + rescue ex : ParserException + raise ParserException.new("Assert (pre-assertion): #{ex.message}") + else unless @f.call(result.value) raise ParserException.new("Assert: predicate failed for <#{result.value}>") end - result + return result end end - class Satisfy(T) < Assert(T, T) + class Satisfy(T) < Parser(T, T) + @p : Assert(T, T) + def initialize(&block : T -> Bool) - super(AnyToken(T).new, &block) + @p = AnyToken(T).new.assert(&block) + end + + def parse(tokens : TokenStream(T)) : Result(T, T) + @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Satisfy: #{ex.message}") end end @@ -164,8 +176,12 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, V) @p1.parse(tokens) - rescue ParserException - @p2.parse(tokens) + rescue ex1 : ParserException + begin + @p2.parse(tokens) + rescue ex2 : ParserException + raise ParserException.new("Alt (#{ex1.message}), (#{ex2.message})") + end end end @@ -177,6 +193,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, U) result = @p.parse(tokens) Result.new(result.tokens, @f.call(result.value)) + rescue ex : ParserException + raise ParserException.new("Map: #{ex.message}") end end @@ -189,6 +207,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, V) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Phrase: #{ex.message}") end end @@ -197,8 +217,18 @@ module Parcom end def parse(tokens : TokenStream(T)) : Result(T, {V, U}) - r1 = @p1.parse(tokens) - r2 = @p2.parse(r1.tokens) + begin + r1 = @p1.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Plus (left): #{ex.message}") + end + + begin + r2 = @p2.parse(r1.tokens) + rescue ex : ParserException + raise ParserException.new("Plus (right): #{ex.message}") + end + Result.new(r2.tokens, {r1.value, r2.value}) end end @@ -244,6 +274,8 @@ module Parcom end Result.new(tokens, parsed) + rescue ex : ParserException + raise ParserException.new("Sequence: #{ex.message}") end end @@ -259,6 +291,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, Array(T)) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Tokens: #{ex.message}") end end @@ -280,6 +314,8 @@ module Parcom end Result.new(tokens, parsed) + rescue ex : ParserException + raise ParserException.new("Many: #{ex.message}") end end @@ -292,6 +328,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, Array(V)) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Some: #{ex.message}") end end @@ -305,6 +343,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, Array(V)) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Exactly: #{ex.message}") end end @@ -319,6 +359,8 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, Array(V)) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("AtLeast: #{ex.message}") end end @@ -331,10 +373,27 @@ module Parcom def parse(tokens : TokenStream(T)) : Result(T, Array(V)) @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("AtMost: #{ex.message}") end end - class Between + class Between(T, V) < Parser(T, Array(V)) + @p : Map(T, {Array(V), Array(V)}, Array(V)) + + def initialize(i : Int, j : Int, p : Parser(T, V)) + lower = i < j ? i : j + upper = (i - j).abs + @p = (Exactly.new(lower, p) + AtMost.new(upper, p)).map do |tup| + tup[0] + tup[1] + end + end + + def parse(tokens : TokenStream(T)) : Result(T, Array(V)) + @p.parse(tokens) + rescue ex : ParserException + raise ParserException.new("Between: #{ex.message}") + end end class StopAt |
