aboutsummaryrefslogtreecommitdiff
path: root/src/Parser.hs
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2022-08-12 22:53:06 +0100
committerJuan J. Martinez <jjm@usebox.net>2022-08-12 22:53:06 +0100
commit279f04cb63e45ceb9a9df82540d5362565b8b37b (patch)
treebf71e8d7829e6ccf29320dacaf7c4742423683c5 /src/Parser.hs
downloadmicro-lang-hs-279f04cb63e45ceb9a9df82540d5362565b8b37b.tar.gz
micro-lang-hs-279f04cb63e45ceb9a9df82540d5362565b8b37b.zip
Initial import
Diffstat (limited to 'src/Parser.hs')
-rw-r--r--src/Parser.hs148
1 files changed, 148 insertions, 0 deletions
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)