2016-05-14 46 views
1

对于一个项目,我们的任务是构建一个控制一个小型arduino机器人的haskell分析器/评估器。因此,首先,我已经对已经实现的解析器设置进行了一些研究,并碰到了这个:https://wiki.haskell.org/Parsing_a_simple_imperative_languageParsec:扩展工作分析器给出了奇怪的结果

之后(无可否认)复制粘贴代码,我开始测试它。它工作\ o /。 现在是扩展其功能的时候了。

编辑的代码:

data Stmt = Seq [Stmt] 
    | Assign String AExpr 
    | If BExpr Stmt Stmt 
    | While BExpr Stmt 
    | Motor String AExpr 
    | Skip 
     deriving (Show) 

Token.reservedNames = [ "if" 
           , "then" 
           , "else" 
           , "while" 
           , "do" 
           , "skip" 
           , "true" 
           , "false" 
           , "not" 
           , "and" 
           , "or", "set" , "to" 
           ] 
statement' :: Parser Stmt 
statement' = ifStmt 
     <|> whileStmt 
     <|> skipStmt 
     <|> assignStmt 
     <|> motorStatement 

motorStatement :: Parser Stmt 
motorStatement = 
    do reserved "set" 
    var <- identifier 
    reserved "to" 
    expr <- aExpression 
    return $ Motor var expr 

这些是代码的唯一件我编辑。 为了测试这一切,我做了一个小testfile的:

x := 4; 
x := 6; 

上面的代码beatifully解析我改变过,但之后我加入了变化,我得到以下错误

< (line 3, column 1): 
< unexpected end of input 
< expecting "if", "while", "skip", identifier or "set" 

用我有限的知识Haskell,我无法弄清楚为什么这个“unexpected end of input”正在发生。

也许一些哈斯克勒在这里能够指出我的错误。

回答

2

我不确信在您进行更改之前您的输入已正确解析。语句列表解析使用sepBy1

sequenceOfStmt = 
    do list <- (sepBy1 statement' semi) 
    -- If there's only one statement return it without using Seq. 
    return $ if length list == 1 then head list else Seq list 

sequenceOfStmt是在贪婪的,如果它看到一个分号会希望看到另一个statement'。因此,分号应该被视为语句分隔符而不是语句终结符。

尝试运行这些测试,看看如何sepBy1的行为:

import Text.Parsec 
import Text.Parsec.Combinator 

p1 = sepBy1 (char 'a') (char ';') 

test1 = parseTest p1 "a;a"  -- OK 
test2 = parseTest p1 "a;a;"  -- FAILS 

为了探讨这个问题,我已经把源的ParseWhile语言上lpaste.net:http://lpaste.net/163332

+0

读您的回复做出我很快意识到我的“错误”。每个分号都使它需要/需要另一行/语句。而且由于空行不能转换为类型,因此出错。谢谢你,先生! – MrKickkiller