----------------------------------------------------------------------------- -- | -- Module : Text.ParserCombinators.Parsec.Combinator -- Copyright : (c) Daan Leijen 1999-2001 -- License : BSD-style (see the file libraries/parsec/LICENSE) -- -- Maintainer : daan@cs.uu.nl -- Stability : provisional -- Portability : portable -- -- Commonly used generic combinators -- ----------------------------------------------------------------------------- module Text.ParserCombinators.Parsec.Combinator ( choice , count , between , option, optional , skipMany1 , many1 , sepBy, sepBy1 , endBy, endBy1 , sepEndBy, sepEndBy1 , chainl, chainl1 , chainr, chainr1 , eof, notFollowedBy -- tricky combinators , manyTill, lookAhead, anyToken ) where import Control.Monad import Text.ParserCombinators.Parsec.Prim ---------------------------------------------------------------- -- ---------------------------------------------------------------- choice :: [GenParser tok st a] -> GenParser tok st a choice ps = foldr (<|>) mzero ps option :: a -> GenParser tok st a -> GenParser tok st a option x p = p <|> return x optional :: GenParser tok st a -> GenParser tok st () optional p = do{ p; return ()} <|> return () between :: GenParser tok st open -> GenParser tok st close -> GenParser tok st a -> GenParser tok st a between open close p = do{ open; x <- p; close; return x } skipMany1 :: GenParser tok st a -> GenParser tok st () skipMany1 p = do{ p; skipMany p } {- skipMany p = scan where scan = do{ p; scan } <|> return () -} many1 :: GenParser tok st a -> GenParser tok st [a] many1 p = do{ x <- p; xs <- many p; return (x:xs) } {- many p = scan id where scan f = do{ x <- p ; scan (\tail -> f (x:tail)) } <|> return (f []) -} sepBy1,sepBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a] sepBy p sep = sepBy1 p sep <|> return [] sepBy1 p sep = do{ x <- p ; xs <- many (sep >> p) ; return (x:xs) } sepEndBy1, sepEndBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a] sepEndBy1 p sep = do{ x <- p ; do{ sep ; xs <- sepEndBy p sep ; return (x:xs) } <|> return [x] } sepEndBy p sep = sepEndBy1 p sep <|> return [] endBy1,endBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a] endBy1 p sep = many1 (do{ x <- p; sep; return x }) endBy p sep = many (do{ x <- p; sep; return x }) count :: Int -> GenParser tok st a -> GenParser tok st [a] count n p | n <= 0 = return [] | otherwise = sequence (replicate n p) chainr,chainl :: GenParser tok st a -> GenParser tok st (a -> a -> a) -> a -> GenParser tok st a chainr p op x = chainr1 p op <|> return x chainl p op x = chainl1 p op <|> return x chainr1,chainl1 :: GenParser tok st a -> GenParser tok st (a -> a -> a) -> GenParser tok st a chainl1 p op = do{ x <- p; rest x } where rest x = do{ f <- op ; y <- p ; rest (f x y) } <|> return x chainr1 p op = scan where scan = do{ x <- p; rest x } rest x = do{ f <- op ; y <- scan ; return (f x y) } <|> return x ----------------------------------------------------------- -- Tricky combinators ----------------------------------------------------------- anyToken :: Show tok => GenParser tok st tok anyToken = tokenPrim show (\pos tok toks -> pos) Just eof :: Show tok => GenParser tok st () eof = notFollowedBy anyToken "end of input" notFollowedBy :: Show tok => GenParser tok st tok -> GenParser tok st () notFollowedBy p = try (do{ c <- p; unexpected (show [c]) } <|> return () ) manyTill :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a] manyTill p end = scan where scan = do{ end; return [] } <|> do{ x <- p; xs <- scan; return (x:xs) } lookAhead :: GenParser tok st a -> GenParser tok st a lookAhead p = do{ state <- getParserState ; x <- p ; setParserState state ; return x }