From 279f04cb63e45ceb9a9df82540d5362565b8b37b Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Fri, 12 Aug 2022 22:53:06 +0100 Subject: Initial import --- src/Parser.hs | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/Parser.hs (limited to 'src/Parser.hs') diff --git a/src/Parser.hs b/src/Parser.hs new file mode 100644 index 0000000..1c21700 --- /dev/null +++ b/src/Parser.hs @@ -0,0 +1,148 @@ +module Parser where + +import Ast +import Data.Maybe (isJust) +import Lexer +import Text.Parsec +import qualified Text.Parsec.Expr as E +import Text.Parsec.String (Parser) + +binary s f assoc = E.Infix (reservedOp s >> return (BinOp f)) assoc + +opTable = + [ [ binary "*" Mul E.AssocLeft, + binary "/" Div E.AssocLeft + ], + [ binary "+" Plus E.AssocLeft, + binary "-" Minus E.AssocLeft + ] + ] + +expr :: Parser Expr +expr = E.buildExpressionParser opTable factor + +number :: Parser Expr +number = do + pos <- getPosition + n <- integer + return $ Num n pos + +variable :: Parser Expr +variable = do + pos <- getPosition + var <- identifier + return $ Var var pos + +typ :: Parser Type +typ = do + p <- identifier + return $ Type p + +typFn :: Parser Type +typFn = do + p <- parens $ commaSep typ + r <- optionMaybe $ do + reserved "->" + typ + return $ FuncType p r + +type' :: Parser Type +type' = do + try typFn + <|> typ "type" + +arg :: Parser (String, Type, SourcePos) +arg = do + pos <- getPosition + i <- identifier + _ <- colonSep "\":\" before type" + t <- type' "type" + return $ (i, t, pos) + +fdef :: Ident -> Bool -> SourcePos -> Parser Expr +fdef ident priv pos = do + args <- parens $ commaSep arg + rtyp <- + optionMaybe + ( do + _ <- colonSep "\":\" before type" + rtyp <- type' "return type" + return $ rtyp + ) + body <- braces $ many statement + return $ Func ident args rtyp body priv pos + +function :: Parser Expr +function = do + pos <- getPosition + priv <- optionMaybe $ reserved "private" + reserved "def" + ident <- identifier + fdef ident (isJust priv) pos + +lambdaId :: SourcePos -> Ident +lambdaId s = + "lambda" ++ "@" ++ show (sourceLine s) ++ "," ++ show (sourceColumn s) + +lambda :: Parser Expr +lambda = do + pos <- getPosition + fdef (lambdaId pos) True pos + +return' :: Parser Expr +return' = do + pos <- getPosition + reserved "return" + value <- optionMaybe expr + reservedOp ";" + return $ Return value pos + +call :: Parser Expr +call = do + pos <- getPosition + ident <- try lambda <|> variable + args <- parens $ commaSep expr + return $ Call ident args pos + +factor :: Parser Expr +factor = + try number + <|> try call + <|> try lambda + <|> try variable + <|> parens expr + +exprStmt :: Parser Expr +exprStmt = do + e <- expr <|> factor + reservedOp ";" + return $ e + +statement :: Parser Expr +statement = do + try exprStmt + <|> return' + +module' :: Parser Expr +module' = do + pos <- getPosition + reserved "module" + ident <- identifier + return $ Module ident pos + +program :: Parser [Expr] +program = do + m <- module' + n <- + many $ do + try function + -- TODO: variable decl + <|> statement "statement" + return $ [m] ++ n + +parse :: Parser [Expr] +parse = program + +parseFromFile p fname = do + input <- readFile fname + return (runParser p () fname input) -- cgit v1.2.3