126 lines
3.1 KiB
Haskell
126 lines
3.1 KiB
Haskell
module Parser where
|
|
|
|
import Text.Parsec hiding (tokens)
|
|
import Text.Parsec.String
|
|
import Lexer (tokens)
|
|
import Token
|
|
import Expression
|
|
|
|
parseExpression :: String -> Either ParseError Expr
|
|
parseExpression s = do
|
|
tokns <- parse tokens "lexical error" s
|
|
expr <- parse anyExpressionEOF "parsing error" tokns
|
|
return expr
|
|
|
|
anyExpressionEOF :: GenParser Token st Expr
|
|
anyExpressionEOF = do
|
|
expr <- anyExpression
|
|
_ <- eof
|
|
return expr
|
|
|
|
anyExpression :: GenParser Token st Expr
|
|
anyExpression = do
|
|
expr <- intE <|> quotedE <|> try setE <|> try nilE <|> try consE <|> try lambdaE <|> varE <|> listE
|
|
return expr
|
|
|
|
------------------------------------------------------------
|
|
|
|
listE :: GenParser Token st Expr
|
|
listE = do
|
|
_ <- parseLeftParenT
|
|
exprs <- many anyExpression
|
|
_ <- parseRightParenT
|
|
return $ toCons exprs
|
|
where toCons [] = NilE
|
|
toCons (x:xs) = ConsE x (toCons xs)
|
|
|
|
intE :: GenParser Token st Expr
|
|
intE = do
|
|
(IntT num) <- parseIntT
|
|
return $ IntE num
|
|
|
|
quotedE :: GenParser Token st Expr
|
|
quotedE = do
|
|
_ <- parseApostropheT
|
|
expr <- anyExpression
|
|
return $ QuotedE expr
|
|
|
|
consE :: GenParser Token st Expr
|
|
consE = do
|
|
_ <- parseLeftParenT
|
|
_ <- parseConsT
|
|
expr1 <- anyExpression
|
|
expr2 <- anyExpression
|
|
_ <- parseRightParenT
|
|
return $ ConsE expr1 expr2
|
|
|
|
varE :: GenParser Token st Expr
|
|
varE = do
|
|
(SymbolT var) <- parseSymbolT
|
|
return $ VarE var
|
|
|
|
nilE :: GenParser Token st Expr
|
|
nilE = do
|
|
_ <- parseNilT
|
|
return NilE
|
|
|
|
setE :: GenParser Token st Expr
|
|
setE = do
|
|
_ <- parseLeftParenT
|
|
_ <- parseSetT
|
|
(SymbolT var) <- parseSymbolT
|
|
expr <- anyExpression
|
|
_ <- parseRightParenT
|
|
return $ SetE var expr
|
|
|
|
lambdaE :: GenParser Token st Expr
|
|
lambdaE = do
|
|
_ <- parseBackslashT
|
|
(SymbolT arg) <- parseSymbolT
|
|
body <- anyExpression
|
|
return $ LambdaE arg body
|
|
|
|
------------------------------------------------------------
|
|
|
|
satisfyT :: (Stream s m a, Show a) => (a -> Bool) -> ParsecT s u m a
|
|
satisfyT f = tokenPrim show
|
|
(\pos _ _ -> incSourceColumn pos 1)
|
|
(\t -> if f t then Just t else Nothing)
|
|
|
|
parseBackslashT :: GenParser Token st Token
|
|
parseBackslashT = satisfyT (== BackslashT)
|
|
|
|
parseLeftParenT :: GenParser Token st Token
|
|
parseLeftParenT = satisfyT (== LeftParenT)
|
|
|
|
parseRightParenT :: GenParser Token st Token
|
|
parseRightParenT = satisfyT (== RightParenT)
|
|
|
|
parseApostropheT :: GenParser Token st Token
|
|
parseApostropheT = satisfyT (== ApostropheT)
|
|
|
|
parseSetT :: GenParser Token st Token
|
|
parseSetT = satisfyT isSetT
|
|
where isSetT (SymbolT "set!") = True
|
|
isSetT _ = False
|
|
|
|
parseNilT :: GenParser Token st Token
|
|
parseNilT = satisfyT isNilT
|
|
where isNilT (SymbolT "nil") = True
|
|
isNilT _ = False
|
|
|
|
parseConsT :: GenParser Token st Token
|
|
parseConsT = satisfyT isConsT
|
|
where isConsT (SymbolT "cons") = True
|
|
isConsT _ = False
|
|
|
|
parseSymbolT :: GenParser Token st Token
|
|
parseSymbolT = satisfyT isSymbolT
|
|
where isSymbolT (SymbolT _) = True
|
|
isSymbolT _ = False
|
|
|
|
parseIntT :: GenParser Token st Token
|
|
parseIntT = satisfyT isIntT
|
|
where isIntT (IntT _) = True
|
|
isIntT _ = False
|