Parsec:扩展工作分析器给出了奇怪的结果
问题描述:
对于一个项目,我们的任务是构建一个控制一个小型arduino机器人的haskell分析器/评估器。因此,首先,我已经对已经实现的解析器设置进行了一些研究,并碰到了这个:https://wiki.haskell.org/Parsing_a_simple_imperative_language。Parsec:扩展工作分析器给出了奇怪的结果
之后(无可否认)复制粘贴代码,我开始测试它。它工作\ 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
”正在发生。
也许一些哈斯克勒在这里能够指出我的错误。
答
我不确信在您进行更改之前您的输入已正确解析。语句列表解析使用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
读您的回复做出我很快意识到我的“错误”。每个分号都使它需要/需要另一行/语句。而且由于空行不能转换为类型,因此出错。谢谢你,先生! – MrKickkiller