From 34d9f21c6ab529e415f38a5a886b1b612bcbd3bc Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sun, 10 Mar 2019 00:13:32 +0100 Subject: Initial --- src/Haskell/Parser.hs | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/Haskell/Parser.hs (limited to 'src/Haskell/Parser.hs') diff --git a/src/Haskell/Parser.hs b/src/Haskell/Parser.hs new file mode 100644 index 0000000..0f55a63 --- /dev/null +++ b/src/Haskell/Parser.hs @@ -0,0 +1,133 @@ +module Haskell.Parser where + +import Control.Monad +import Control.Monad.Identity +import Haskell.AST +import Haskell.Parser.Def +import Text.Parsec +-- import Text.Parsec.IndentParsec.Combinator +import Text.Parsec.IndentParsec.Prim + + +type Parser a = GenIndentParsecT HaskellLike String () Identity a + +parseAST :: String -> String -> Either ParseError AST +parseAST fname source = runIdentity $ runGIPT pAST () fname source + +pAST :: Parser AST +pAST = do + whiteSpace + tops <- pToplevel `sepBy` someNewline + eof + return $ AST tops + +pToplevel :: Parser Toplevel +pToplevel = choice [TopClass <$> pClass + ,TopInst <$> pInst + ,TopData <$> pData + ,TopDecl <$> pDecl + ,TopDef <$> pDef] + +pData :: Parser Data +pData = do + reserved "data" + n <- typeident + vars <- many varident + ty <- choice [do reservedOp "=" + pConstr `sepBy` reservedOp "|" + ,return []] + return $ Data n vars ty + where + pConstr = liftM2 (,) typeident (many pType) + +pClass :: Parser Class +pClass = do + reserved "class" + n <- typeident + vars <- many varident + reserved "where" + decls <- bracesBlock (semiSepOrFoldedLines pDecl) + return $ Class n vars decls + +pInst :: Parser Inst +pInst = do + reserved "instance" + (n, ty) <- pType >>= \case + TyRef n [ty] -> return (n, ty) + _ -> fail "invalid instance head" + reserved "where" + decls <- bracesBlock (semiSepOrFoldedLines pDef) + return $ Inst n ty decls + +pDecl :: Parser Decl +pDecl = do + n <- try (varident <* reservedOp "::") + ty <- pType + return $ Decl n ty + +pDef :: Parser Def +pDef = do + n <- varident + args <- many varident + reservedOp "=" + body <- pExpr + case args of + [] -> return $ Def n body + _ -> return $ Def n (Lam args body) + +pType :: Parser Type +pType = foldr1 TyFun <$> pSimpleType `sepBy` reservedOp "->" + where + pSimpleType :: Parser Type + pSimpleType = choice [do n <- typeident + args <- many pAtomicType + return (TyRef n args) + ,pAtomicType] + + pAtomicType :: Parser Type + pAtomicType = choice [typeident >>= \n -> return (TyRef n []) + ,TyVar <$> varident + ,parens (pType `sepBy` comma) >>= \case + [ty] -> return ty + tys -> return (TyTup tys)] + +pExpr :: Parser Expr +pExpr = pLam <|> pCase <|> pApp + where + pSimpleExpr = choice [LitNum <$> integer + ,Ref <$> (identifier <|> try (parens operator)) + ,parens pExpr] + + pLam = do + reservedOp "\\" + args <- many1 varident + body <- pExpr + return $ Lam args body + + pApp = App <$> pSimpleExpr <*> many pSimpleExpr + + pCase = do + reserved "case" + n <- varident + reserved "of" + arms <- bracesBlock (semiSepOrFoldedLines pCaseArm) + return $ Case n arms + + pCaseArm = do + pat <- pLargePat + reservedOp "->" + ex <- pExpr + return (pat, ex) + +pSimplePat :: Parser Pat +pSimplePat = choice [lexeme (string "_") >> return PatAny + ,PatVar <$> varident + ,typeident >>= \n -> return (PatCon n []) + ,parens pLargePat] + +pLargePat :: Parser Pat +pLargePat = choice [PatCon <$> typeident <*> many pSimplePat + ,pSimplePat] + +someNewline :: Parser () +someNewline = many (oneOf " \t") >> char '\n' >> whiteSpace -- cgit v1.2.3-54-g00ecf