Parsec:扩展一个有效的解析器会得到奇怪的结果

时间:2016-05-14 16:39:15

标签: haskell parsec

对于一个项目,我们的任务是构建一个控制一个小型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能够指出错误。

1 个答案:

答案 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