diff options
Diffstat (limited to 'Sil/Util')
-rw-r--r-- | Sil/Util/Parser.dcl | 6 | ||||
-rw-r--r-- | Sil/Util/Parser.icl | 95 |
2 files changed, 64 insertions, 37 deletions
diff --git a/Sil/Util/Parser.dcl b/Sil/Util/Parser.dcl index 8474b78..6f5929c 100644 --- a/Sil/Util/Parser.dcl +++ b/Sil/Util/Parser.dcl @@ -17,7 +17,7 @@ from Sil.Error import :: Error fromPositioned :: (Positioned a) -> a -:: ParseState a +:: *ParseState a :: ParseInput a = PI_NewLine @@ -25,7 +25,7 @@ fromPositioned :: (Positioned a) -> a makeParseState :: [ParseInput a] -> ParseState a -:: Parser a b = Parser ((ParseState a) -> (MaybeError Error b, ParseState a)) +:: Parser a b = Parser (*(ParseState a) -> *(MaybeError Error b, *ParseState a)) instance Functor (Parser a) instance Applicative (Parser a) @@ -35,7 +35,7 @@ instance Alternative (Parser a) class name a :: a -> String instance name String -runParser :: (Parser a b) (ParseState a) -> (MaybeError Error b, ParseState a) +runParser :: (Parser a b) *(ParseState a) -> *(MaybeError Error b, *ParseState a) getPositioner :: Parser a (b -> Positioned b) (<?>) :: (Parser a b) Error -> Parser a b fail :: Parser a b diff --git a/Sil/Util/Parser.icl b/Sil/Util/Parser.icl index 34cf057..83da78c 100644 --- a/Sil/Util/Parser.icl +++ b/Sil/Util/Parser.icl @@ -1,5 +1,6 @@ implementation module Sil.Util.Parser +from StdFunc import iter import StdList import StdOverloaded @@ -16,26 +17,47 @@ import Sil.Error fromPositioned :: (Positioned a) -> a fromPositioned p = p.pos_val -:: ParseState a = - { ps_line :: Int - , ps_input :: [ParseInput a] - , ps_read :: [ParseInput a] +:: *ParseState a = + { ps_line :: Int + , ps_input :: [ParseInput a] + , ps_read :: [ParseInput a] + , ps_pos :: Int + , ps_commits :: [Int] } makeParseState :: [ParseInput a] -> ParseState a -makeParseState i = {ps_line=1, ps_input=i, ps_read=[]} +makeParseState i = + { ps_line = 1 + , ps_input = i + , ps_read = [] + , ps_pos = 0 + , ps_commits = [] + } nextToken :: (ParseState a) -> (Maybe a, ParseState a) -nextToken ps = case ps.ps_input of - [] -> (Nothing, ps) - [PI_Token t:i] -> (Just t, {ps & ps_read=[PI_Token t:ps.ps_read], ps_input=i}) - [PI_NewLine:i] -> nextToken {ps & ps_line=ps.ps_line + 1, ps_read=[PI_NewLine:ps.ps_read], ps_input=i} +nextToken ps=:{ps_input=[]} = (Nothing, ps) +nextToken ps=:{ps_input=[i:is]} = case i of + PI_Token t -> (Just t, {advance & ps_pos=ps.ps_pos + 1}) + PI_NewLine -> nextToken {advance & ps_line=ps.ps_line + 1} +where + advance = {ps & ps_read=[i:ps.ps_read], ps_input=is} tokenBack :: (ParseState a) -> ParseState a -tokenBack ps = case ps.ps_read of - [] -> ps - [PI_Token t:r] -> {ps & ps_read=r, ps_input=[PI_Token t:ps.ps_input]} - [PI_NewLine:r] -> tokenBack {ps & ps_read=r, ps_input=[PI_NewLine:ps.ps_input], ps_line=ps.ps_line-1} +tokenBack ps=:{ps_read=[]} = ps +tokenBack ps=:{ps_read=[r:rs]} = case r of + PI_Token t -> {rewind & ps_pos=ps.ps_pos - 1} + PI_NewLine -> tokenBack {rewind & ps_line=ps.ps_line-1} +where + rewind = {ps & ps_read=rs, ps_input=[r:ps.ps_input]} + +commit :: (ParseState a) -> ParseState a +commit ps = {ps & ps_commits=[ps.ps_pos:ps.ps_commits]} + +dropCommit :: (ParseState a) -> ParseState a +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 fmap f m = liftM f m @@ -45,30 +67,35 @@ instance Applicative (Parser a) where (<*>) sf p = ap sf p instance Monad (Parser a) where - bind p f = Parser \st -> case runParser p st of - (Ok r, rest) -> runParser (f r) rest - (Error e, _) -> (Error e, st) + 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 empty = Parser \st -> (Error $ UnknownError "empty in Parser", st) - (<|>) p1 p2 = Parser \st -> case runParser p1 st of - (Ok r, rest) -> (Ok r, rest) - (Error e1, rest) -> case runParser p2 st of - (Error e2, rest) -> (Error e2, st) - (Ok r, rest) -> (Ok r, rest) + (<|>) 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) instance name String where name s = s -runParser :: (Parser a b) (ParseState a) -> (MaybeError Error b, ParseState a) +doPS :: ((ParseState a) -> ParseState a) -> Parser a () +doPS f = Parser \st -> (Ok (), f st) + +runParser :: (Parser a b) *(ParseState a) -> *(MaybeError Error b, *ParseState a) runParser (Parser f) i = f i getPositioner :: Parser a (b -> Positioned b) -getPositioner = Parser \st -> (Ok \x -> {pos_line=st.ps_line, pos_val=x}, st) +getPositioner = Parser \st=:{ps_line} -> (Ok \x -> {pos_line=ps_line, pos_val=x}, st) (<?>) :: (Parser a b) Error -> Parser a b (<?>) p e = Parser \i -> case runParser p i of - (Error _, rest) -> (Error e, rest) - o -> o + (Error _, st) -> (Error e, st) + o -> o fail :: Parser a b fail = empty @@ -93,19 +120,19 @@ check f = peek >>= \r -> if (f r) (pure r) fail (until) p guard = try $ until` p guard [] where until` :: (Parser a b) (Parser a c) [b] -> Parser a [b] - until` p guard acc = Parser \st -> case runParser guard st of - (Ok _, rest) -> (Ok acc, rest) - (Error _, _) -> case runParser p st of - (Ok r, rest) -> runParser (until` p guard [r:acc]) rest - (Error e, _) -> (Error e, st) + until` p guard acc = Parser \st -> case runParser guard (commit st) of + (Ok _, st) -> (Ok acc, dropCommit st) + (Error _, st) -> case runParser p (commit $ restoreCommit st) of + (Ok r, st) -> runParser (until` p guard [r:acc]) (dropCommit st) + (Error e, st) -> (Error e, restoreCommit st) try :: (Parser a b) -> Parser a b try p = Parser \st -> case runParser p st of - (Error e, _) -> (Error e, st) - (Ok r, rest) -> (Ok r, rest) + (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 = satisfy ((==) a) <?> P_Expected (name a) list :: [a] -> Parser a [a] | ==, name a list as = mapM item as @@ -118,4 +145,4 @@ seplist sep p = liftM2 (\es e-> es ++ [e]) (some (p <* item sep)) p eof :: Parser a () eof = Parser \st -> case nextToken st of (Nothing, st) -> (Ok (), st) - (_, st) -> (Error $ P_Expected "eof", st) + (t, st) -> (Error $ P_Expected "eof", st) |