Parsing try函数解析lambda表达式

Parsing try函数解析lambda表达式,parsing,haskell,lambda,Parsing,Haskell,Lambda,我是Haskell的新手,正在尝试实现一个“Lambda演算”解析器,该解析器将用于读取Lambda reducer的输入。。首先需要从文本文件中解析绑定“identifier=expression;”,然后在最后只有一个表达式。。 到目前为止,它只能解析绑定,并且在单独遇到表达式时显示错误。。当我尝试使用try或选项功能时,会出现类型不匹配错误: 绑定不应该返回任何内容,但我尝试添加一个return语句,它还返回了一个类型不匹配错误: 无法将类型“[Expr]”与“Expr”匹配 预期类型:T

我是Haskell的新手,正在尝试实现一个“Lambda演算”解析器,该解析器将用于读取Lambda reducer的输入。。首先需要从文本文件中解析绑定“identifier=expression;”,然后在最后只有一个表达式。。 到目前为止,它只能解析绑定,并且在单独遇到表达式时显示错误。。当我尝试使用
try
选项
功能时,会出现类型不匹配错误:

绑定不应该返回任何内容,但我尝试添加一个return语句,它还返回了一个类型不匹配错误:

无法将类型“[Expr]”与“Expr”匹配
预期类型:Text.Parsec.Prim.ParsecT
[Char]u0 Data.Functor.Identity.Identity[Expr]
实际类型:Text.Parsec.Prim.ParsecT
[Char]u0 Data.Functor.Identity.Identity[[Expr]]
在“()”的第二个参数中,即“expressions”
如果要同时允许这两种情况,请不要使用
您的
程序
解析器的主要工作是使用

program = do
      spaces
      try bindings <|> expressions
      spaces >> eof
如果有更多的
“binding”
类型提示,则更容易找到此错误,这样您就可以更清楚地看到预期的内容

endBy
不需要
many
您收到的错误消息来自该行

expressions = many (endBy expression eol)
应该是哪一个

expressions :: Parser [Expr]
expressions = endBy expression eol
endBy
的工作原理类似于
sebby
——您不需要在其上使用
many
,因为它已经解析了许多

如果使用更强的数据类型树,则更容易找到此错误,因此:

使用
尝试处理常见前缀
您遇到的一个难以调试的问题是在解析表达式时出现错误
需要空格或“=”
。如果我们考虑到这一点,我们期望的唯一位置是在绑定中,因此当我们给绑定一个表达式时,它一定是解析绑定的一部分。只有当表达式以标识符开头时才会发生这种情况,就像绑定一样

binding
看到第一个标识符并说“没关系,伙计们,我有这个”,但随后没有找到
=
,并给出一个错误,我们希望它回溯并让
表达式
试一试。关键的一点是,我们已经使用了标识符输入,我们希望使用它
try
正适合这样做

try
封装
绑定
解析器,因此如果失败,我们将返回到行的开头,并将其交给
表达式

binding = try (do
          (Var id) <- identifier
          _ <- char '='
          spaces
          exp <- expression
          spaces
          eol <?> "end of line"
          return $ Eq id exp
        <?> "binding")
例如,不要对字母这样做,而是对重要的事情。重要的事情是判断的问题,但我要从标识符开始。(您可以使用
在结果中不包含类似
=
的语法。)

修订守则: 在重构类型和使用Applicative之前


然后谢谢你。。我试图进行您提到的修改,但是当解析器到达只有表达式的行时,它会显示一个错误&需要绑定:
code
unexpected”(“需要空格或“=”我将绑定定义为:data binding=Eq Symbol Expr绑定的类型是:bindings::parser[binding]binding::Parser binding是否正确?是的。我正在使用更正但未改进的版本(如)解析括号内的表达式。如果这不起作用,能否发布
“Program.txt”
?解析表达式时仍返回相同的错误,“Program.txt”仅在删除所有绑定后才包含表达式:
eq(div(add 2 7)(sub 5 2))3;
@user3305447 Ah yes-
表达式和
绑定都可以以标识符开头,因此
绑定
有一个尝试,但预期
=
失败。这是常见的前缀问题。请参阅新版本的答案。
expressions = many (endBy expression eol)
expressions :: Parser [Expr]
expressions = endBy expression eol
binding = try (do
          (Var id) <- identifier
          _ <- char '='
          spaces
          exp <- expression
          spaces
          eol <?> "end of line"
          return $ Eq id exp
        <?> "binding")
--<program> ::= <spaces> [<bindings>] <expressions>
data Program = Prog [Binding] [Expr]
program = spaces >> Prog <$> bindings <*> expressions   

-- <expression> ::=  <abstraction> | factors
data Expression = Ab Abstraction | Fa [Factor] 
expression = Ab <$> abstraction <|> Fa <$> factors   <?> "expression"