在Parsec中递归使用语句解析器

时间:2013-03-04 20:30:38

标签: haskell parsec

我有一个ifelse解析器,而不是能够在一个解析嵌入的ifelse语句 类似java的语言,但它没有识别内在的ifelse。另外,如果有人能告诉我一个更好的方法来处理ifelseParser中的空白,我会很感激。

if (~(position > 16)) { 
                 if (~((value & mask) = 0)) { 
                       do Memory.poke(8000 + position, 1); 
                 } else { 
                       do Memory.poke(8000 + position, 0); 
                 } 
} else { let loop = false; } 

ifelseParser没有获取整个表达式,缺少内部的if-else语句。

 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)

1 个答案:

答案 0 :(得分:4)

您正在使用变量stmt来保存“if”语句和“else”语句。所以当你这样做时:

 return $ IfElse iff expr stmt el stmt           

...我猜我stmt只包含最近分配的值,来自“else”部分。