module Parse.ParseCore(
Pos,ParseError,ParseResult,ParseBad,ParseGood,Parser
,initError,initBad,initGood -- Start values for parseError,parseBad, parseGood
,parseit -- entry for parsing
,parse,ap,chk,orelse,into -- The core
,token -- parse terminal
,parseFail -- Failing parser
,maxError -- Keep "best" error message
) where
import Util.Extra(noPos,Pos)
infixl 5 `ap`
infixl 5 `chk`
infixr 4 `orelse`
--- Define types
-- parameters:
-- i = input to be parsed
-- a = resulting syntax tree
-- c = other return value
type ParseError = (Pos,String,[String])
type ParseResult a i = Either ParseError (a,i,ParseError)
type ParseBad a i = ParseError -> ParseResult a i
type ParseGood a i c = a -> i -> ParseError -> ParseResult c i
type Parser a i c = ParseGood a i c -> ParseBad c i -> i -> ParseError -> ParseResult c i
--- start values
initError :: ParseError
initError = (noPos,"Hu?",["No error"])
initBad :: ParseBad a i
initBad = \err -> Left err
initGood :: ParseGood a i a
initGood = \res input err -> Right (res,input,err)
parseit :: Parser a i a -> i -> Either ParseError a
parseit p input = parseit' (p initGood initBad input initError)
parseit' :: Either err (a, b, c) -> Either err a
parseit' (Left err) = Left err
parseit' (Right (a,_,_)) = Right a
--- The core
parse :: a -> Parser a i b
parse x = \good bad -> good x
ap :: Parser (a->b) i c -> Parser a i c -> Parser b i c
ap x y = \good bad ->
x (\u -> y (\v -> let uv = u v in seq uv (good uv) ) bad)
bad
chk :: Parser b i c -> Parser a i c -> Parser b i c
chk x y = \good bad ->
x (\u -> y (\_ -> good u) bad)
bad
into :: Parser a i c -> (a->Parser b i c) -> Parser b i c
into x y = \good bad ->
x (\u -> y u good bad)
bad
orelse :: Parser a i b -> Parser a i b -> Parser a i b
x `orelse` y = \good bad input ->
x good (y good bad input) input
token :: (Show b) => (Pos -> b -> Either String d) -> Parser d [(Pos,b,e,f)] h
token p = \good bad ((pos,t,_,_):input) err ->
case p pos t of
Right tt' -> good tt' input err
Left f -> bad (maxError (pos,show t,[f]) err)
parseFail :: Parser a i b
parseFail = \good bad input err -> bad err
maxError :: Ord a => (a, b, [a1]) -> (a, b, [a1]) -> (a, b, [a1])
maxError (a@(pa,ta,ma)) (b@(pb,tb,mb)) =
if pa > pb then a
else if pb > pa then b
else (pa,ta,ma++mb)
|