module Graphics.Implicit.ExtOpenScad.Parser.Statement where
import Graphics.Implicit.Definitions
import Text.ParserCombinators.Parsec hiding (State)
import Text.ParserCombinators.Parsec.Expr
import Graphics.Implicit.ExtOpenScad.Definitions
import Graphics.Implicit.ExtOpenScad.Parser.Util
import Graphics.Implicit.ExtOpenScad.Parser.Expr
parseProgram name s = parse program name s where
program = do
sts <- many1 computation
eof
return sts
computation :: GenParser Char st StatementI
computation =
(try $ do
genSpace
s <- tryMany [
ifStatementI,
forStatementI,
throwAway,
userModuleDeclaration
]
genSpace
return s
) <|> (try $ do
genSpace
s <- tryMany [
echo,
assignment,
include--,
--use
]
genSpace
char ';'
genSpace
return s
) <|> (try $ do
genSpace
s <- userModule
genSpace
return s
)
suite :: GenParser Char st [StatementI]
suite = (fmap return computation <|> do
char '{'
genSpace
stmts <- many (try computation)
genSpace
char '}'
return stmts
) <?> " suite"
throwAway :: GenParser Char st StatementI
throwAway = do
line <- lineNumber
genSpace
oneOf "%*"
genSpace
computation
return $ StatementI line DoNothing
include :: GenParser Char st StatementI
include = (do
line <- lineNumber
use <- (string "include" >> return False)
<|> (string "use" >> return True )
genSpace
string "<"
filename <- many (noneOf "<>")
string ">"
return $ StatementI line $ Include filename use
) <?> "include "
assignment :: GenParser Char st StatementI
assignment =
(try $ do
line <- lineNumber
pattern <- patternMatcher
genSpace
char '='
genSpace
valExpr <- expression 0
return $ StatementI line$ pattern := valExpr
) <|> (try $ do
line <- lineNumber
varSymb <- (try $ string "function" >> space >> genSpace >> variableSymb)
<|> variableSymb
genSpace
char '('
genSpace
argVars <- sepBy patternMatcher (try $ genSpace >> char ',' >> genSpace)
genSpace
char ')'
genSpace
char '='
genSpace
valExpr <- expression 0
return $ StatementI line $ Name varSymb := LamE argVars valExpr
)<?> "assignment "
echo :: GenParser Char st StatementI
echo = do
line <- lineNumber
string "echo"
genSpace
char '('
genSpace
exprs <- expression 0 `sepBy` (try $ genSpace >> char ',' >> genSpace)
genSpace
char ')'
return $ StatementI line $ Echo exprs
ifStatementI :: GenParser Char st StatementI
ifStatementI = (do
line <- lineNumber
string "if"
genSpace
char '('
bexpr <- expression 0
char ')'
genSpace
sTrueCase <- suite
genSpace
sFalseCase <- try (string "else" >> genSpace >> suite ) <|> (return [])
return $ StatementI line $ If bexpr sTrueCase sFalseCase
) <?> "if "
forStatementI :: GenParser Char st StatementI
forStatementI = (do
line <- lineNumber
string "for"
genSpace
char '('
genSpace
pattern <- patternMatcher
genSpace
char '='
vexpr <- expression 0
char ')'
genSpace
loopContent <- suite
return $ StatementI line $ For pattern vexpr loopContent
) <?> "for "
userModule :: GenParser Char st StatementI
userModule = do
line <- lineNumber
name <- variableSymb;
genSpace;
args <- moduleArgsUnit
genSpace;
s <- ( try suite <|> (genSpace >> char ';' >> return []))
return $ StatementI line $ ModuleCall name args s
userModuleDeclaration :: GenParser Char st StatementI
userModuleDeclaration = do
line <- lineNumber
string "module"
genSpace;
newModuleName <- variableSymb;
genSpace;
args <- moduleArgsUnitDecl
genSpace;
s <- suite
return $ StatementI line $ NewModule newModuleName args s
moduleArgsUnit :: GenParser Char st [(Maybe String, Expr)]
moduleArgsUnit = do
char '(';
genSpace
args <- sepBy (
(try $ do
symb <- variableSymb
genSpace
char '='
genSpace
expr <- expression 0
return $ (Just symb, expr)
) <|> (try $ do
symb <- variableSymb;
genSpace
char '('
genSpace
argVars <- sepBy variableSymb (try $ genSpace >> char ',' >> genSpace)
char ')'
genSpace
char '=';
genSpace
expr <- expression 0;
return $ (Just symb, LamE (map Name argVars) expr)
) <|> (do {
expr <- expression 0;
return (Nothing, expr)
})
) (try $ genSpace >> char ',' >> genSpace)
genSpace
char ')'
return args
moduleArgsUnitDecl :: GenParser Char st [(String, Maybe Expr)]
moduleArgsUnitDecl = do
char '(';
genSpace
argTemplate <- sepBy (
(try $ do
symb <- variableSymb;
genSpace
char '='
genSpace
expr <- expression 0
return (symb, Just expr)
) <|> (try $ do
symb <- variableSymb;
genSpace
char '('
genSpace
argVars <- sepBy variableSymb (try $ genSpace >> char ',' >> genSpace)
char ')'
genSpace
char '='
genSpace
expr <- expression 0
return (symb, Just expr)
) <|> (do {
symb <- variableSymb;
return (symb, Nothing)
})
) (try $ genSpace >> char ',' >> genSpace);
genSpace
char ')';
return argTemplate
lineNumber = fmap sourceLine getPosition