aboutsummaryrefslogtreecommitdiff
path: root/Sil/Util
diff options
context:
space:
mode:
Diffstat (limited to 'Sil/Util')
-rw-r--r--Sil/Util/Parser.dcl16
-rw-r--r--Sil/Util/Parser.icl49
2 files changed, 44 insertions, 21 deletions
diff --git a/Sil/Util/Parser.dcl b/Sil/Util/Parser.dcl
index e5d1cce..14dc022 100644
--- a/Sil/Util/Parser.dcl
+++ b/Sil/Util/Parser.dcl
@@ -1,6 +1,6 @@
definition module Sil.Util.Parser
-from StdOverloaded import class ==
+from StdOverloaded import class ==, class toString
from Control.Applicative import class Applicative, class Alternative
from Control.Monad import class Monad
@@ -13,10 +13,12 @@ from Sil.Error import :: Error
:: *ParseState a
:: ParsePosition =
- { pp_line :: Int
+ { pp_line :: Int
+ , pp_token :: Int
}
class getPos a :: a -> ParsePosition
+instance getPos ParsePosition
:: ParseInput a
= PI_NewLine
@@ -37,13 +39,15 @@ instance name String
runParser :: (Parser a b) *(ParseState a) -> *(MaybeError Error b, *ParseState a)
getPosition :: Parser a ParsePosition
(<?>) :: (Parser a b) Error -> Parser a b
+(<#>) :: (Parser a b) String -> Parser a b | toString a
fail :: Parser a b
top :: Parser a a
peek :: Parser a a
satisfy :: (a -> Bool) -> Parser a a
check :: (a -> Bool) -> Parser a a
(until) infix 2 :: (Parser a b) (Parser a c) -> Parser a [b]
-item :: a -> Parser a a | ==, name a
-list :: [a] -> Parser a [a] | ==, name a
-seplist :: a (Parser a b) -> Parser a [b] | ==, name a
-eof :: Parser a ()
+item :: a -> Parser a a | ==, name, toString a
+list :: [a] -> Parser a [a] | ==, name, toString a
+seplist :: a (Parser a b) -> Parser a [b] | ==, name, toString a
+seplistUntil :: a a (Parser a b) -> Parser a [b] | ==, name, toString a
+eof :: Parser a () | toString a
diff --git a/Sil/Util/Parser.icl b/Sil/Util/Parser.icl
index 92bc08f..e730313 100644
--- a/Sil/Util/Parser.icl
+++ b/Sil/Util/Parser.icl
@@ -14,6 +14,8 @@ import Data.Maybe
import Sil.Error
+instance getPos ParsePosition where getPos pp = pp
+
:: *ParseState a =
{ ps_line :: Int
, ps_input :: [ParseInput a]
@@ -56,27 +58,31 @@ dropCommit ps = {ps & ps_commits=tl ps.ps_commits}
restoreCommit :: (ParseState a) -> ParseState a
restoreCommit ps=:{ps_commits=[c:cs]} = iter (ps.ps_pos - c) tokenBack {ps & ps_commits=cs}
-instance Functor (Parser a) where
+instance Functor (Parser a)
+where
fmap f m = liftM f m
-instance Applicative (Parser a) where
+instance Applicative (Parser a)
+where
pure a = Parser \st -> (Ok a, st)
(<*>) sf p = ap sf p
-instance Monad (Parser a) where
+instance Monad (Parser a)
+where
bind p f = Parser \st -> case runParser p (commit st) of
(Error e, st) -> (Error e, restoreCommit st)
(Ok r, st) -> case runParser (f r) st of
(Ok r, st) -> (Ok r, dropCommit st)
(Error e, st) -> (Error e, restoreCommit st)
-instance Alternative (Parser a) where
+instance Alternative (Parser a)
+where
empty = Parser \st -> (Error $ UnknownError "empty in Parser", st)
(<|>) p1 p2 = Parser \st -> case runParser p1 (commit st) of
(Ok r, st) -> (Ok r, dropCommit st)
(Error e1, st) -> case runParser p2 (commit $ restoreCommit st) of
(Ok r, st) -> (Ok r, dropCommit st)
- (Error e2, st) -> (Error e2, restoreCommit st)
+ (Error e2, st) -> (Error $ max e1 e2, restoreCommit st)
instance name String where name s = s
@@ -87,13 +93,16 @@ runParser :: (Parser a b) *(ParseState a) -> *(MaybeError Error b, *ParseState a
runParser (Parser f) i = f i
getPosition :: Parser a ParsePosition
-getPosition = Parser \st=:{ps_line} -> (Ok {pp_line=ps_line}, st)
+getPosition = Parser \st=:{ps_line,ps_pos} -> (Ok {pp_line=ps_line,pp_token=ps_pos}, st)
(<?>) :: (Parser a b) Error -> Parser a b
(<?>) p e = Parser \i -> case runParser p i of
(Error _, st) -> (Error e, st)
o -> o
+(<#>) :: (Parser a b) String -> Parser a b | toString a
+(<#>) p what = p <|> (getPosition >>= \pos -> peek >>= \e -> Parser \st -> (Error $ P_Expected (errpos pos) what e, st))
+
fail :: Parser a b
fail = empty
@@ -128,18 +137,28 @@ where
(Error e, st) -> (Error e, st)
(Ok r, st) -> (Ok r, st)
-item :: a -> Parser a a | ==, name a
-item a = satisfy ((==) a) <?> P_Expected (name a)
+item :: a -> Parser a a | ==, name, toString a
+item a = satisfy ((==) a) <#> name a
-list :: [a] -> Parser a [a] | ==, name a
+list :: [a] -> Parser a [a] | ==, name, toString a
list as = mapM item as
-seplist :: a (Parser a b) -> Parser a [b] | ==, name a
-seplist sep p = liftM2 (\es e-> es ++ [e]) (some (p <* item sep)) p
- <|> liftM pure p
+seplist :: a (Parser a b) -> Parser a [b] | ==, name, toString a
+seplist sep p = liftM2 (\e es -> [e:es]) p (many (p <* item sep))
<|> pure empty
-eof :: Parser a ()
-eof = Parser \st -> case nextToken st of
+seplistUntil :: a a (Parser a b) -> Parser a [b] | ==, name, toString a
+seplistUntil end sep p =
+ liftM2 (\e es -> [e:es]) p ((item sep *> p) until` (item end))
+ <|> liftM pure (p <* item end)
+ <|> (pure empty <* item end)
+where
+ (until`) infix 2 :: (Parser a b) (Parser a c) -> Parser a [b]
+ (until`) p1 guard = (p1 until guard) >>= \xs -> case xs of
+ [] -> fail
+ xs -> pure xs
+
+eof :: Parser a () | toString a
+eof = Parser \st=:{ps_line,ps_pos} -> case nextToken st of
(Nothing, st) -> (Ok (), st)
- (t, st) -> (Error $ P_Expected "eof", st)
+ (Just t, st) -> (Error $ P_Expected (errpos {pp_line=ps_line,pp_token=ps_pos}) "eof" t, st)