我一直在尝试使用parsec为类型化的lambda演算编写一个解析器,但它一直卡在一个循环中,导致一个<>错误。对我来说一切似乎都很好;我可能误解了有关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
答案 0 :(得分:2)
如果您对错误消息更具体,可能会有所帮助。但我怀疑问题在于你有一个左递归语法:例如,arrTy
可以以anyType
开头,可以是arrTy
。
直接在自上而下的解析器(包括组合解析器,如Parsec)中实现时,这种特性会导致无限循环。 Parsec提供各种设施来解决这个问题;但是,解决特定问题最方便的方法可能还需要重新学习一些语法。