title: Using statement parsers recursively in Parsec
body: <p>I have an ifelse parser than should be able to parse embedded ifelse statements in a<br>
  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.</p>
  
  <pre><code>if (~(position &gt; 16)) { 
                   if (~((value &amp; mask) = 0)) { 
                         do Memory.poke(8000 + position, 1); 
                   } else { 
                         do Memory.poke(8000 + position, 0); 
                   } 
  } else { let loop = false; } 
  </code></pre>
  
  <p>The ifelseParser is not picking up whole expression, missing inner if-else statement.</p>
  
  <pre><code> Right (IfElse "if" (ExprOpTerm (Unary "~" (ExprOpTerm (SimpleExpr (ExprOpTerm 
  (VarTerm "position") [("&gt;",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 &lt;- reserved' "if"                                                                                                                                                                                                                       
    whiteSpace                                                                                                                                                                                                                                  
    char '('                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    expr &lt;- getExprParser                                                                                                                                                                                                                       
    whiteSpace                                                                                                                                                                                                                                  
    char ')'                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    char '{'                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    stmt &lt;- many1 statementsParser                                                                                                                                                                                                              
    whiteSpace                                                                                                                                                                                                                                  
    char '}'                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    el &lt;- reserved' "else"                                                                                                                                                                                                                      
    whiteSpace                                                                                                                                                                                                                                  
    char '{'                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    stmts &lt;- many1 statementsParser                                                                                                                                                                                                              
    whiteSpace                                                                                                                                                                                                                                  
    char '}'                                                                                                                                                                                                                                    
    whiteSpace                                                                                                                                                                                                                                  
    return $ IfElse iff expr stmt el stmts         
  
  statementsParser :: Parser Statement                                                                                                                                                                                                          
  statementsParser = do                                                                                                                                                                                                                         
    try subLetParser &lt;|&gt;  try letParser &lt;|&gt; try whileParser &lt;|&gt;                                                                                                                                                                                 
      try ifelseParser &lt;|&gt; try ifParser &lt;|&gt;                                                                                                                                                                                                     
      try doParser &lt;|&gt; (try returnExpParser &lt;|&gt; try returnParser)                                                                                                                                                                               
  
  
  subRoutineParser :: Parser Term                                                                                                                                                                                                               
  subRoutineParser = do                                                                                                                                                                                                                         
    whiteSpace                                                                                                                                                                                                                                  
    sub &lt;- subCallParser                                                                                                                                                                                                                        
    return $ Subroutine sub                                                                                                                                                                                                                     
  
  getExprParser :: Parser Expr                                                                                                                                                                                                                  
  getExprParser = do                                                                                                                                                                                                                            
    whiteSpace                                                                                                                                                                                                                                  
    term &lt;- (try subRoutineParser &lt;|&gt;                                                                                                                                                                                                           
                   try intVal &lt;|&gt;                                                                                                                                                                                                               
                   try stringVal &lt;|&gt;                                                                                                                                                                                                            
                   try keyWordVal &lt;|&gt;                                                                                                                                                                                                           
                   try varExpParser &lt;|&gt;                                                                                                                                                                                                         
                   try varVal &lt;|&gt;                                                                                                                                                                                                               
                   try simpleExpr &lt;|&gt;                                                                                                                                                                                                           
                   try unaryOpExpr)                                                                                                                                                                                                             
    op &lt;- many getExpP                                                                                                                                                                                                                          
    return $ ExprOpTerm term op                                                                                                                                                                                                                 
  
  getExpP :: Parser (String,Term)                                                                                                                                                                                                               
  getExpP = do                                                                                                                                                                                                                                  
    whiteSpace                                                                                                                                                                                                                                  
    op &lt;- choice $ map string ops                                                                                                                                                                                                               
    term &lt;- (try subRoutineParser &lt;|&gt;                                                                                                                                                                                                           
            try intVal &lt;|&gt;                                                                                                                                                                                                                      
            try stringVal &lt;|&gt;                                                                                                                                                                                                                   
            try keyWordVal &lt;|&gt;                                                                                                                                                                                                                  
            try varExpParser &lt;|&gt;                                                                                                                                                                                                                
            try varVal &lt;|&gt;                                                                                                                                                                                                                      
            try simpleExpr &lt;|&gt;                                                                                                                                                                                                                  
            try unaryOpExpr)                                                                                                                                                                                                                    
    return $ (op,term)
  </code></pre>