module Parser.Combinator where import qualified Text.ParserCombinators.Parsec as Parsec import Text.ParserCombinators.Parsec (Parser, (<|>)) import Control.Monad.HT (void) import Control.Monad (liftM2) space :: Parser () space = void (Parsec.char ' ') <|> Parsec.try (Parsec.newline >> continue) newline :: Parser () newline = do void Parsec.newline Parsec.notFollowedBy continue continue :: Parser () continue = do Parsec.skipMany $ Parsec.char ' ' void $ Parsec.char '$' spaces :: Parser () spaces = Parsec.skipMany space garbage :: Parser () garbage = Parsec.skipMany $ Parsec.noneOf "\n" infixl 1 `followedBy` followedBy :: Parser a -> Parser () -> Parser a followedBy p end = do a <- p; end; return a oneLine :: Parser a -> Parser a oneLine p = p `followedBy` newline lexeme :: Parser a -> Parser a lexeme p = p `followedBy` spaces identifier :: Parser String identifier = lexeme $ liftM2 (:) Parsec.letter (Parsec.many (Parsec.alphaNum <|> Parsec.char '_')) commaSep :: Parser a -> Parser [a] commaSep = flip Parsec.sepBy (lexeme $ Parsec.char ',') commaSep1 :: Parser a -> Parser [a] commaSep1 = flip Parsec.sepBy1 (lexeme $ Parsec.char ',') parens :: Parser a -> Parser a parens = Parsec.between (lexeme $ Parsec.char '(') (lexeme $ Parsec.char ')') keyword :: String -> Parser () keyword str = void $ lexeme $ Parsec.string str