module Parser (parseProgram, parseExpression, parseFile, parseString) where import Text.ParserCombinators.Parsec import qualified Text.ParserCombinators.Parsec.Token as Tk import Text.ParserCombinators.Parsec.Language import Debug.Trace import Data.Char (isSpace) import Data.List (partition) import AST -- cnv f s = case f s of -- Left err -> Left $ show err -- Right r -> Right $ r parseProgram s = (parse pProg "") $ insertSemi s parseExpression = (parse pExp "") parseString s = parseProgram s parseFile filename = return . parseProgram =<< readFile filename -- | |insertSemi| inserts ";" after every "\n". insertSemi :: String -> String insertSemi [] = [] insertSemi [x] = [x] insertSemi ('\r':'\n':x) | not (isSpace $ head x) = ';':'\r':'\n':insertSemi x insertSemi ('\n':x) | not (isSpace $ head x) = ';':'\n':insertSemi x insertSemi ('\r':x) | not (isSpace $ head x) = ';':'\r':insertSemi x insertSemi (a:x) = a:insertSemi x varId :: Parser String varId = do { c <- lower ; cs <- many (alphaNum <|> char '_') ; return $ (c:cs) } conId :: Parser String conId = do { c <- upper ; cs <- many (alphaNum <|> char '_') ; return $ (c:cs) } number :: Parser Int number = do { cs <- many1 digit ; return $ read cs } myLexer = Tk.makeTokenParser haskellDef -- $ emptyDef { -- commentStart = "{-" -- , commentEnd = "-}" -- , commentLine = "--" -- , reservedNames = ["case", "class", "data", "default", "deriving", "do", "else", "if", "import", "in", "infix", "infixl", "infixr", "instance", "let", "module", "newtype", "of", "then", "type", "where", "_" ] -- } parens = Tk.parens myLexer symbol = Tk.symbol myLexer comma = Tk.comma myLexer lexeme = Tk.lexeme myLexer reserved = Tk.reserved myLexer brackets = Tk.brackets myLexer whiteSpace = Tk.whiteSpace myLexer semi = Tk.semi myLexer pProg = do { skipMany (whiteSpace >> semi) ; ds <- sepEndBy (pDecl) (many1 (whiteSpace >> semi)) -- many (lexeme pDecl) ; return $ assignIDsAST (AST $ ds) } pDecl = do { whiteSpace ; pos <- getPosition ; fName <- lexeme varId ; ps <- many1 pAPat -- parens (pPats) ; whiteSpace ; symbol "=" ; e <- pExp ; return $ Decl (Name fName) FTUndet ps e } -- pPats = sepBy pPat comma {- pPat ::= pAPat : pPat | pCPat pCPat ::= C pAPat ... pAPat | pAPat pAPat ::= C | x | BList | (pPat) BList ::= [ pPat, ..., pPat ] -} pcons x y = PCon Nothing TUndet (Name "Cons") [x,y] pnil = PCon Nothing TUndet (Name "Nil") [] -- list pattern pPat = do { whiteSpace ; pos <- getPosition ; try ( do { p1 <- pAPat ; symbol ":" ; p2 <- pPat ; return $ pcons p1 p2 } ) <|> pCPat } -- constructor pattern pCPat = do { whiteSpace ; pos <- getPosition ; do { c <- lexeme conId ; ps <- many pAPat ; return $ PCon Nothing TUndet (Name c) ps } <|> pAPat } -- pattern need not to be enclosed with parens pAPat = do { whiteSpace ; pos <- getPosition ; do { c <- lexeme conId ; ps <- many pAPat ; return $ PCon Nothing TUndet (Name c) [] } <|> do { c <- lexeme number ; return $ PCon Nothing TUndet (Name $ show c) [] } <|> do { c <- lexeme varId ; return $ PVar Nothing TUndet (Name c) } <|> do { pBListPat } <|> do { parens pPat } } -- [p1, ..., pn] pBListPat = do { ps <- brackets (sepBy pPat comma) ; return $ foldr pcons pnil ps} -- pPat = do { whiteSpace -- ; pos <- getPosition -- ; try pList -- <|> -- do { c <- lexeme conId -- ; ps <- many pAPat -- option [] $ parens pPats -- ; return $ PCon Nothing TUndet (Name c) ps } -- <|> -- pAPat } -- pAPat = do { whiteSpace -- ; pos <- getPosition -- ; do { c <- lexeme conId -- ; return $ PCon Nothing TUndet (Name c) [] } -- <|> -- do { c <- lexeme number -- ; return $ PCon Nothing TUndet (Name $ show c) [] } -- <|> -- do { c <- lexeme varId -- ; return $ PVar Nothing TUndet (Name c) } -- <|> -- -- do { pBList } -- -- <|> -- do { parens pPat } -- } -- pList = do { whiteSpace -- ; pos <- getPosition -- ; try (do { p1 <- pAPat -- ; symbol ":" -- ; p2 <- pPat -- ; return $ PCon Nothing TUndet (Name $ "Cons") [p1,p2] }) -- <|> -- pAPat } -- pTExp = do { whiteSpace -- ; pos <- getPosition -- ; do { c <- lexeme conId -- ; es <- option [] $ parens (sepBy (pTExp) comma) -- ; return $ ECon Nothing TUndet (Name c) es } -- <|> -- do { c <- lexeme $ number -- ; return $ ECon Nothing TUndet (Name $ show c) [] } -- <|> -- do { c <- lexeme varId -- ; do { es <- parens (sepBy (pArg) comma) -- ; return $ EFun Nothing TUndet (Name c) es } -- <|> -- do { return $ EVar Nothing TUndet (Name c) } } -- <|> -- do { _ <- string "(" -- ; c <- pTExp -- ; _ <- string ")" -- ; return c }} {- pExp ::= pAExp : pExp | pAppExp pAppExp ::= C pAExp ... pAExp | f pAExp ... pAExp | pAExp pAPat ::= C | n | x | pBListExp | (pExp) pBListExp ::= [ pExp, ..., pExp ] -} econs x y = ECon Nothing TUndet (Name $ "Cons") [x,y] enil = ECon Nothing TUndet (Name $ "Nil") [] -- Cons pExp = do { whiteSpace ; pos <- getPosition ; try (do { e1 <- pAExp ; symbol ":" ; e2 <- pExp ; return $ econs e1 e2 }) <|> pAppExp } -- Application pAppExp = do { whiteSpace ; pos <- getPosition ; do { c <- lexeme conId ; es <- many pAExp -- option [] $ parens (sepBy (pExp) comma) ; return $ ECon Nothing TUndet (Name c) es } <|> do { c <- lexeme varId ; do { es <- many1 pAExp -- parens (sepBy (pExp) comma) ; return $ EFun Nothing TUndet (Name c) es } <|> do { return $ EVar Nothing TUndet (Name c) } } <|> pAExp } -- Atomic pAExp = do { whiteSpace ; pos <- getPosition ; do { c <- lexeme conId ; return $ ECon Nothing TUndet (Name c) [] } <|> do { c <- lexeme number ; return $ ECon Nothing TUndet (Name $show c) [] } <|> do { c <- lexeme varId ; return $ EVar Nothing TUndet (Name c) } <|> do { pBListExp } <|> do { parens pExp } } -- [e1, ..., en] pBListExp = do { es <- brackets (sepBy pExp comma) ; return $ foldr econs enil es} -- pExp = do { whiteSpace -- ; pos <- getPosition -- ; do { c <- lexeme conId -- ; es <- many pAExp -- option [] $ parens (sepBy (pExp) comma) -- ; return $ ECon Nothing TUndet (Name c) es } -- <|> -- do { c <- lexeme $ number -- ; return $ ECon Nothing TUndet (Name $ show c) [] } -- <|> -- do { c <- lexeme varId -- ; do { es <- many1 pAExp -- parens (sepBy (pExp) comma) -- ; return $ EFun Nothing TUndet (Name c) es } -- <|> -- do { return $ EVar Nothing TUndet (Name c) } } -- <|> -- do { parens pExp } -- } -- pArg = do { pos <- getPosition -- ; c <- lexeme varId -- ; return $ EVar Nothing TUndet (Name c)}