2013-03-04 33 views
0

我有一个ifelse分析器,它应该能够解析类似于java的语言中的嵌入式ifelse语句,但它不能识别内部的ifelse。另外,如果有人能够给我一个更好的方法来处理ifelseParser中的空白,我将不胜感激。在Parsec中递归地使用语句分析器

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) 
+0

你为什么编辑这个问题?它看起来像你应用修复,所以它不再被破坏。现在任何人都会在墙上试探一下,试图弄清楚为什么它不是... – pat 2013-03-05 02:12:37

+0

空白通常是通过使用'lexeme'解析器来处理的,它在你感兴趣的标记之后吞噬任何空白另外,你是否需要每个'if'有一个'else'? Java不需要这个。 – pat 2013-03-05 02:14:19

+0

@pat如果他们阅读答案,不是。然后他们会知道为什么它被打破。我有两个解析器,一个用于If和一个用于IfElse。我会研究一下lexeme。 – 2013-03-05 04:45:12

回答

4

您正在使用可变stmt保留两个“如果”语句和“其他”的语句。所以,当你这样做:

return $ IfElse iff expr stmt el stmt   

...我猜stmt只包含最近指派的值,它是从“其他”部分。

+0

很好,并且谢谢。 – 2013-03-04 20:40:18