Haskell parsec给出&lt; <loop>&gt;错误

时间:2016-02-06 18:59:44

标签: parsing haskell parsec

我一直在尝试使用parsec为类型化的lambda演算编写一个解析器,但它一直卡在一个循环中,导致一个&lt;&gt;错误。对我来说一切似乎都很好;我可能误解了有关parsec的一些事情。

{-# LANGUAGE UnicodeSyntax #-}

module Parser where

import Semantics ( NmTerm(..)
                 , Ty(..))

import Text.ParserCombinators.Parsec (Parser(..)
                                     , ParseError
                                     , try
                                     , oneOf
                                     , char
                                     , digit
                                     , satisfy
                                     , many1
                                     , choice
                                     , chainl1
                                     , alphaNum
                                     , eof
                                     , letter
                                     , parse)

import qualified Text.Parsec.Token as T
import qualified Text.Parsec.Language as L
import qualified Text.Parsec.Expr as E
import Control.Applicative ((<|>))

------------
-- LEXING --
------------

lexer ∷ T.TokenParser ()
lexer = T.makeTokenParser
        $ L.emptyDef { T.identStart      = letter
                     , T.identLetter     = alphaNum
                     , T.reservedOpNames = ["lambda", ".", ":", "->"]
                     , T.reservedNames   = ["true", "false", "Bool"]
                     , T.opLetter        = oneOf ".:"
                     }

parens ∷ Parser a → Parser a
parens = T.parens lexer

natural ∷ Parser Integer
natural = T.natural lexer

reserved ∷ String → Parser ()
reserved = T.reserved lexer

reservedOp ∷ String → Parser ()
reservedOp = T.reservedOp lexer

identifier ∷ Parser String
identifier = T.identifier lexer

whiteSpace ∷ Parser ()
whiteSpace = T.whiteSpace lexer

-------------------------------------------------------------------------------
-------------------------------------- PARSING --------------------------------
-------------------------------------------------------------------------------
variable ∷ Parser NmTerm
variable = identifier >>= \x → return $ NmVar x

true ∷ Parser NmTerm
true = reserved "true" >> return NmTrue

false ∷ Parser NmTerm
false = reserved "false" >> return NmFalse

bool ∷ Parser NmTerm
bool = true <|> false

boolTy ∷ Parser Ty
boolTy = reserved "Bool" >> return TyBool

arrTy ∷ Parser Ty
arrTy = do
  τ₁ ← anyType
  whiteSpace
  reservedOp "->"
  whiteSpace
  τ₂ ← anyType
  return $ TyArr τ₁ τ₂

anyType ∷ Parser Ty
anyType = arrTy <|> boolTy

abstraction ∷ Parser NmTerm
abstraction = do
  reservedOp "lambda"
  whiteSpace
  x ← identifier
  reservedOp ":"
  τ ← anyType
  reservedOp "."
  whiteSpace
  body ← expr
  return $ NmAbs x τ body

expr ∷ Parser NmTerm
expr =  abstraction
    <|> variable
    <|> bool

parseExpr ∷ String → NmTerm
parseExpr t = case parse expr "" t of
                Left err  → error $ show err
                Right ast → ast

1 个答案:

答案 0 :(得分:2)

如果您对错误消息更具体,可能会有所帮助。但我怀疑问题在于你有一个左递归语法:例如,arrTy可以以anyType开头,可以是arrTy

直接在自上而下的解析器(包括组合解析器,如Parsec)中实现时,这种特性会导致无限循环。 Parsec提供各种设施来解决这个问题;但是,解决特定问题最方便的方法可能还需要重新学习一些语法。