module Parser.Conditions (
pIf,
pWhile,
pFor
) where
import Text.Megaparsec
import qualified Data.Text as DT
import AST.Ast (Ast(..))
import Parser.Lexer
import Parser.Expression (pExpr)
pIfCondition :: Parser Ast -> Parser (Maybe Ast, Ast)
pIfCondition :: Parser Ast -> Parser (Maybe Ast, Ast)
pIfCondition Parser Ast
pVarDefParam = Parser (Maybe Ast, Ast) -> Parser (Maybe Ast, Ast)
forall a. Parser a -> Parser a
parens (Parser (Maybe Ast, Ast) -> Parser (Maybe Ast, Ast))
-> Parser (Maybe Ast, Ast) -> Parser (Maybe Ast, Ast)
forall a b. (a -> b) -> a -> b
$ do
maybeInit <- Parser Ast -> ParsecT Void Text Identity (Maybe Ast)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Ast -> Parser Ast
forall a. Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try Parser Ast
pVarDefParam Parser Ast -> Parser Ast -> Parser Ast
forall a.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Ast -> Parser Ast
forall a. Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (Parser Ast
pExpr Parser Ast -> ParsecT Void Text Identity Text -> Parser Ast
forall a b.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity b -> ParsecT Void Text Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT Void Text Identity Text
semicolon))
condition <- pExpr
return (maybeInit, condition)
pElseBranch :: Parser Ast -> Parser Ast -> Parser Ast
pElseBranch :: Parser Ast -> Parser Ast -> Parser Ast
pElseBranch Parser Ast
pVarDefParam Parser Ast
pBlockParam = Ast -> Parser Ast -> Parser Ast
forall (m :: * -> *) a. Alternative m => a -> m a -> m a
option Ast
AVoid (Parser Ast -> Parser Ast) -> Parser Ast -> Parser Ast
forall a b. (a -> b) -> a -> b
$ do
_ <- Text -> ParsecT Void Text Identity Text
pKeyword (String -> Text
DT.pack String
"else")
try (pIf pVarDefParam pBlockParam) <|> pBlockParam
buildIfAst :: Maybe Ast -> Ast -> Ast -> Ast -> Ast
buildIfAst :: Maybe Ast -> Ast -> Ast -> Ast -> Ast
buildIfAst Maybe Ast
initStmt Ast
cond Ast
thenB Ast
elseB =
let ifNode :: Ast
ifNode = Ast -> Ast -> Ast -> Ast
AIf Ast
cond Ast
thenB Ast
elseB
in case Maybe Ast
initStmt of
Just Ast
initInstr -> [Ast] -> Ast
AList [Ast
initInstr, Ast
ifNode]
Maybe Ast
Nothing -> Ast
ifNode
pIf :: Parser Ast -> Parser Ast -> Parser Ast
pIf :: Parser Ast -> Parser Ast -> Parser Ast
pIf Parser Ast
pVarDefParam Parser Ast
pBlockParam = do
_ <- Text -> ParsecT Void Text Identity Text
pKeyword (String -> Text
DT.pack String
"if")
(initStmt, cond) <- pIfCondition pVarDefParam
thenBlock <- pBlockParam
elseBlock <- pElseBranch pVarDefParam pBlockParam
return $ buildIfAst initStmt cond thenBlock elseBlock
pWhile :: Parser Ast -> Parser Ast
pWhile :: Parser Ast -> Parser Ast
pWhile Parser Ast
pBlockParam = do
_ <- Text -> ParsecT Void Text Identity Text
pKeyword (String -> Text
DT.pack String
"while")
cond <- parens pExpr
body <- pBlockParam
return (AWhile cond body)
pForUpdate :: Parser Ast
pForUpdate :: Parser Ast
pForUpdate = Parser Ast -> Parser Ast
forall a. Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (do
name <- ParsecT Void Text Identity Text
pIdentifier
_ <- symbol (DT.pack "=")
val <- pExpr
return (ASetVar name (DT.pack "auto") val))
Parser Ast -> Parser Ast -> Parser Ast
forall a.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Ast
pExpr
pForHeader :: Parser Ast -> Parser (Ast, Ast, Ast)
Parser Ast
pVarDefParam = Parser (Ast, Ast, Ast) -> Parser (Ast, Ast, Ast)
forall a. Parser a -> Parser a
parens (Parser (Ast, Ast, Ast) -> Parser (Ast, Ast, Ast))
-> Parser (Ast, Ast, Ast) -> Parser (Ast, Ast, Ast)
forall a b. (a -> b) -> a -> b
$ do
initS <- Parser Ast -> Parser Ast
forall a. Parser a -> Parser a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try Parser Ast
pVarDefParam
Parser Ast -> Parser Ast -> Parser Ast
forall a.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser Ast
pExpr Parser Ast -> ParsecT Void Text Identity Text -> Parser Ast
forall a b.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity b -> ParsecT Void Text Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT Void Text Identity Text
semicolon)
Parser Ast -> Parser Ast -> Parser Ast
forall a.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Ast
AVoid Ast -> ParsecT Void Text Identity Text -> Parser Ast
forall a b.
a -> ParsecT Void Text Identity b -> ParsecT Void Text Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT Void Text Identity Text
semicolon)
condS <- pExpr <* semicolon
updateS <- try pForUpdate
<|> return AVoid
return (initS, condS, updateS)
pFor :: Parser Ast -> Parser Ast -> Parser Ast
pFor :: Parser Ast -> Parser Ast -> Parser Ast
pFor Parser Ast
pVarDefParam Parser Ast
pBlockParam = do
_ <- Text -> ParsecT Void Text Identity Text
pKeyword (String -> Text
DT.pack String
"for")
(initStmt, cond, updateStmt) <- pForHeader pVarDefParam
body <- pBlockParam
return (AFor initStmt cond updateStmt body)