对于一个项目,我们的任务是构建一个控制一个小型arduino机器人的haskell解析器/评估器。
首先,我基本上对已经实现的解析器设置进行了一些研究,并且遇到了这个问题:https://wiki.haskell.org/Parsing_a_simple_imperative_language。
在(不可否认)复制粘贴代码之后,我开始测试它。它工作\ 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
这些是我编辑过的唯一代码。 为了测试这一切,我做了一个小测试文件:
x := 4;
x := 6;
上述代码在我的更改之前进行了解析,但在我添加更改后,我收到以下错误
< (line 3, column 1):
< unexpected end of input
< expecting "if", "while", "skip", identifier or "set"
由于我对Haskell的了解有限,我无法弄清楚为什么会这样做&#34; unexpected end of input
&#34;正在发生。
也许这里的一些Haskeller能够指出错误。
答案 0 :(得分: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
为了帮助探讨这个问题,我在lpaste.net上提供了ParseWhile语言的来源:http://lpaste.net/163332