aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Hall <hallmatthew314@gmail.com>2023-03-09 21:32:35 +1300
committerMatthew Hall <hallmatthew314@gmail.com>2023-03-09 21:32:35 +1300
commita26ccb40ca98c82f486f1c57334ccc04534a1a23 (patch)
tree4d44196022f2280ecc47e07802c6575c3df1ac1a /src
parent9dc06838e3c78e4a77731cab6bc773846eafce99 (diff)
Implement between + improve error handling
Diffstat (limited to 'src')
-rw-r--r--src/parcom.cr77
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