| module Language.Parser (parseModule) where | |
| import Language.AST | |
| import Language.Lexer (Token(..)) | |
| import qualified Language.Lexer as L | |
| type ParseResult a = Either String a | |
| parseModule :: String -> String -> ParseResult Module | |
| parseModule name src = do | |
| let tokens = L.lex src | |
| stmts <- parseStmts tokens | |
| Right (Module name stmts) | |
| parseStmts :: [Token] -> ParseResult [Stmt] | |
| parseStmts [TEOF] = Right [] | |
| parseStmts [] = Right [] | |
| parseStmts tokens = do | |
| (stmt, rest) <- parseStmt tokens | |
| remaining <- parseStmts rest | |
| Right (stmt : remaining) | |
| parseStmt :: [Token] -> ParseResult (Stmt, [Token]) | |
| parseStmt (TKeyword "def" : TIdent name : rest) = do | |
| let (params, afterParams) = parseParams rest | |
| case afterParams of | |
| (TEquals : exprTokens) -> do | |
| (expr, remaining) <- parseExpr exprTokens | |
| Right (SDef (Ident name) params expr, dropSemi remaining) | |
| _ -> Left $ "Expected '=' after def " ++ name | |
| parseStmt (TKeyword "assert" : rest) = do | |
| (expr, remaining) <- parseExpr rest | |
| Right (SAssert expr, dropSemi remaining) | |
| parseStmt (TKeyword "prove" : TIdent name : TColon : rest) = do | |
| (expr, remaining) <- parseExpr rest | |
| Right (SProve (Ident name) expr, dropSemi remaining) | |
| parseStmt (t:_) = Left $ "Unexpected token: " ++ show t | |
| parseParams :: [Token] -> ([Ident], [Token]) | |
| parseParams (TLParen : rest) = go rest [] | |
| where | |
| go (TRParen : r) acc = (reverse acc, r) | |
| go (TIdent n : r) acc = go r (Ident n : acc) | |
| go r acc = (reverse acc, r) | |
| parseParams tokens = ([], tokens) | |
| parseExpr :: [Token] -> ParseResult (Expr, [Token]) | |
| parseExpr (TKeyword "true" : rest) = Right (ELit True, rest) | |
| parseExpr (TKeyword "false" : rest) = Right (ELit False, rest) | |
| parseExpr (TIdent name : TLParen : rest) = do | |
| (args, remaining) <- parseArgs rest | |
| Right (EApp (Ident name) args, remaining) | |
| parseExpr (TIdent name : rest) = Right (EVar (Ident name), rest) | |
| parseExpr (TLParen : rest) = do | |
| (left, afterLeft) <- parseExpr rest | |
| case afterLeft of | |
| (TNand : rest2) -> do | |
| (right, afterRight) <- parseExpr rest2 | |
| case afterRight of | |
| (TRParen : remaining) -> Right (ENand left right, remaining) | |
| _ -> Left "Expected ')' after NAND expression" | |
| (TRParen : remaining) -> Right (left, remaining) | |
| _ -> Left "Expected '|' or ')' in expression" | |
| parseExpr tokens = Left $ "Cannot parse expression at: " ++ show (take 3 tokens) | |
| parseArgs :: [Token] -> ParseResult ([Expr], [Token]) | |
| parseArgs (TRParen : rest) = Right ([], rest) | |
| parseArgs tokens = do | |
| (expr, remaining) <- parseExpr tokens | |
| case remaining of | |
| (TRParen : rest) -> Right ([expr], rest) | |
| _ -> do | |
| (moreArgs, finalRest) <- parseArgs remaining | |
| Right (expr : moreArgs, finalRest) | |
| dropSemi :: [Token] -> [Token] | |
| dropSemi (TSemicolon : rest) = rest | |
| dropSemi tokens = tokens | |