💕 Adding assignment 3

This commit is contained in:
2024-09-24 14:22:53 +02:00
parent db1f22e983
commit ff778af26f
8 changed files with 432 additions and 0 deletions

View File

@ -0,0 +1,126 @@
module APL.Parser (parseAPL) where
import APL.AST (Exp (..), VName)
import Control.Monad (void)
import Data.Char (isAlpha, isAlphaNum, isDigit)
import Data.Void (Void)
import Text.Megaparsec
( Parsec,
choice,
chunk,
eof,
errorBundlePretty,
many,
notFollowedBy,
parse,
satisfy,
some,
try,
)
import Text.Megaparsec.Char (space)
type Parser = Parsec Void String
lexeme :: Parser a -> Parser a
lexeme p = p <* space
keywords :: [String]
keywords =
[ "if",
"then",
"else",
"true",
"false",
"let",
"in",
"try",
"catch",
"print",
"put",
"get"
]
lVName :: Parser VName
lVName = lexeme $ try $ do
c <- satisfy isAlpha
cs <- many $ satisfy isAlphaNum
let v = c : cs
if v `elem` keywords
then fail "Unexpected keyword"
else pure v
lInteger :: Parser Integer
lInteger =
lexeme $ read <$> some (satisfy isDigit) <* notFollowedBy (satisfy isAlphaNum)
lString :: String -> Parser ()
lString s = lexeme $ void $ chunk s
lKeyword :: String -> Parser ()
lKeyword s = lexeme $ void $ try $ chunk s <* notFollowedBy (satisfy isAlphaNum)
lBool :: Parser Bool
lBool =
lexeme . try . choice $
[ const True <$> lKeyword "true",
const False <$> lKeyword "false"
]
pAtom :: Parser Exp
pAtom =
choice
[ CstInt <$> lInteger,
CstBool <$> lBool,
Var <$> lVName,
lString "(" *> pExp <* lString ")"
]
pLExp :: Parser Exp
pLExp =
choice
[ If
<$> (lKeyword "if" *> pExp)
<*> (lKeyword "then" *> pExp)
<*> (lKeyword "else" *> pExp),
pAtom
]
pExp1 :: Parser Exp
pExp1 = pLExp >>= chain
where
chain x =
choice
[ do
lString "*"
y <- pLExp
chain $ Mul x y,
do
lString "/"
y <- pLExp
chain $ Div x y,
pure x
]
pExp0 :: Parser Exp
pExp0 = pExp1 >>= chain
where
chain x =
choice
[ do
lString "+"
y <- pExp1
chain $ Add x y,
do
lString "-"
y <- pExp1
chain $ Sub x y,
pure x
]
pExp :: Parser Exp
pExp = pExp0
parseAPL :: FilePath -> String -> Either String Exp
parseAPL fname s = case parse (space *> pExp <* eof) fname s of
Left err -> Left $ errorBundlePretty err
Right x -> Right x