module Parse (Parse, Parses, -- data types thenP, returnP, eachP, consP, -- sequencing and success elseP, failP, guardP, filterP, -- alternation and failure starP, plusP, cutP, -- repetition and cut endP, itemP, litP, litsP, exactlyP, -- end, next item, and literals spacesP, lexP, lexicalP, lexactlyP, -- spaces and lexemes asciiP, controlP, printP, spaceP, -- character parsers alphaP, upperP, lowerP, digitP, alphanumP, surroundP, plusSepP, starSepP, parenP, listP, -- surrounds and separators useP) -- using a parser where import Char -- 1.3 #if !defined(__HASKELL98__) #define isAlphaNum isAlphanum #endif infixr 1 `elseP` infix 2 `thenP` infix 2 `eachP` infixr 3 `filterP` infixr 3 `guardP` type Parse a x = a -> [(x, a)] type Parses x = Parse String x thenP :: Parse a x -> (x -> Parse a y) -> Parse a y xP `thenP` kP = \a -> [ (y,c) | (x,b) <- xP a, (y,c) <- kP x b ] returnP :: x -> Parse a x returnP x = \a -> [ (x,a) ] eachP :: Parse a x -> (x -> y) -> Parse a y xP `eachP` f = xP `thenP` (\x -> returnP (f x)) consP :: Parse a x -> Parse a [x] -> Parse a [x] xP `consP` xsP = xP `thenP` (\x -> xsP `thenP` (\xs -> returnP (x:xs))) elseP :: Parse a x -> Parse a x -> Parse a x xP `elseP` yP = \a -> xP a ++ yP a failP :: Parse a x failP = \a -> [] guardP :: Bool -> Parse a x -> Parse a x guardP b xP = if b then xP else failP filterP :: (x -> Bool) -> Parse a x -> Parse a x filterP p xP = xP `thenP` (\x -> p x `guardP` returnP x) starP :: Parse a x -> Parse a [x] starP xP = cutP (plusP xP `elseP` returnP []) plusP :: Parse a x -> Parse a [x] plusP xP = xP `consP` starP xP cutP :: Parse a x -> Parse a x cutP xP = \a -> case xP a of { ~(~(x,b):_) -> [(x,b)] } endP :: Parse [x] () endP = \xs -> if null xs then returnP () xs else failP xs itemP :: Parse [x] x itemP = \xs -> if null xs then failP xs else returnP (head xs) (tail xs) litP :: (Eq x) => x -> Parse [x] x litP c = (\x -> c==x) `filterP` itemP litsP :: (Eq x) => [x] -> Parse [x] [x] litsP [] = returnP [] litsP (c:cs) = litP c `consP` litsP cs exactlyP :: Parse [y] x -> Parse [y] x exactlyP xP = xP `thenP` (\x -> endP `thenP` (\() -> returnP x)) spacesP :: Parses String spacesP = starP spaceP lexicalP :: Parses x -> Parses x lexicalP xP = xP `thenP` (\x -> spacesP `thenP` (\_ -> returnP x)) lexP :: String -> Parses String lexP cs = lexicalP (litsP cs) lexactlyP :: Parses x -> Parses x lexactlyP xP = spacesP `thenP` (\_ -> exactlyP xP) asciiP, controlP, printP, spaceP, upperP :: Parses Char lowerP, alphaP, digitP, alphanumP :: Parses Char asciiP = isAscii `filterP` itemP controlP = isControl `filterP` itemP printP = isPrint `filterP` itemP spaceP = isSpace `filterP` itemP upperP = isUpper `filterP` itemP lowerP = isLower `filterP` itemP alphaP = isAlpha `filterP` itemP digitP = isDigit `filterP` itemP alphanumP = isAlphaNum `filterP` itemP surroundP :: String -> Parses x -> String -> Parses x surroundP l xP r = lexP l `thenP` (\_ -> xP `thenP` (\x -> lexP r `thenP` (\_ -> returnP x))) plusSepP :: String -> Parses x -> Parses [x] plusSepP s xP = xP `consP` starP (lexP s `thenP` (\_ -> xP)) starSepP :: String -> Parses x -> Parses [x] starSepP s xP = plusSepP s xP `elseP` returnP [] parenP :: Parses x -> Parses x parenP xP = surroundP "(" xP ")" listP :: Parses x -> Parses [x] listP xP = surroundP "[" (starSepP "," xP) "]" useP :: x -> Parse a x -> (a -> x) useP failx xP = \a -> case xP a of { [] -> failx; ((x,_):_) -> x }