I have an ifelse parser than should be able to parse embedded ifelse statements in a
java-like language, but it is not recognizing the inner ifelse. Also, if someone could show me a better way to handle the whitespace in the ifelseParser I would appreciate it.
if (~(position > 16)) {
if (~((value & mask) = 0)) {
do Memory.poke(8000 + position, 1);
} else {
do Memory.poke(8000 + position, 0);
}
} else { let loop = false; }
The ifelseParser is not picking up whole expression, missing inner if-else statement.
Right (IfElse "if" (ExprOpTerm (Unary "~" (ExprOpTerm (SimpleExpr (ExprOpTerm
(VarTerm "position") [(">",IntConst 16)])) [])) []) [Let "let" "loop"
(ExprOpTerm (KeywordTerm "false") [])] "else" [Let "let" "loop"
(ExprOpTerm (KeywordTerm "false") [])])
data Statement = Let Keyword VarName Expr
| SubLet Keyword VarName Expr Expr
| If Keyword Expr [Statement]
| IfElse Keyword Expr [Statement] Keyword [Statement]
| While Keyword Expr [Statement]
| Do Keyword SubCall
| ReturnExp Keyword Expr
| NoReturn
| Return Keyword deriving (Show)
ifelseParser :: Parser Statement
ifelseParser = do
whiteSpace
iff <- reserved' "if"
whiteSpace
char '('
whiteSpace
expr <- getExprParser
whiteSpace
char ')'
whiteSpace
char '{'
whiteSpace
stmt <- many1 statementsParser
whiteSpace
char '}'
whiteSpace
el <- reserved' "else"
whiteSpace
char '{'
whiteSpace
stmts <- many1 statementsParser
whiteSpace
char '}'
whiteSpace
return $ IfElse iff expr stmt el stmts
statementsParser :: Parser Statement
statementsParser = do
try subLetParser <|> try letParser <|> try whileParser <|>
try ifelseParser <|> try ifParser <|>
try doParser <|> (try returnExpParser <|> try returnParser)
subRoutineParser :: Parser Term
subRoutineParser = do
whiteSpace
sub <- subCallParser
return $ Subroutine sub
getExprParser :: Parser Expr
getExprParser = do
whiteSpace
term <- (try subRoutineParser <|>
try intVal <|>
try stringVal <|>
try keyWordVal <|>
try varExpParser <|>
try varVal <|>
try simpleExpr <|>
try unaryOpExpr)
op <- many getExpP
return $ ExprOpTerm term op
getExpP :: Parser (String,Term)
getExpP = do
whiteSpace
op <- choice $ map string ops
term <- (try subRoutineParser <|>
try intVal <|>
try stringVal <|>
try keyWordVal <|>
try varExpParser <|>
try varVal <|>
try simpleExpr <|>
try unaryOpExpr)
return $ (op,term)
You are using the variable stmt
to hold both the "if" statements and the "else" statements. So when you do this:
return $ IfElse iff expr stmt el stmt
... I would guess that stmt
only contains the most recently assigned value, which is from the "else" portion.