我不明白如何使用lexeme函数

时间:2013-05-06 16:01:35

标签: haskell whitespace lexer parsec parser-combinators

来自Text.Parsec.Token

lexeme p = do { x <- p; whiteSpace; return x }

似乎lexeme使用解析器p并提供与p具有相同行为的解析器,除了它还会跳过所有尾随空格。正确的吗?

然后以下是怎么回事:

constant :: Parser Int
constant = do
    digits <- many1 digit
    return (read digits)

lexConst :: Parser Int
lexConst = lexeme constant

最后一行导致以下错误消息:

Couldn't match expected type `ParsecT
                                String () Data.Functor.Identity.Identity Int'
            with actual type `ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0'
Expected type: Parser Int
  Actual type: ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0
In the return type of a call of `lexeme'
In the expression: lexeme constant

我做错了什么?

2 个答案:

答案 0 :(得分:6)

您误解了文档,Text.Parsec.Token导出的lexemeGenTokenParser s u m的字段,因此类型为

lexeme :: GenTokenParser s u m -> ParsecT s u m a -> ParsecT s u m a

并且您未在GenTokenParser中提供lexeme constant参数。

您需要先从GenLanguageDef(通常使用makeTokenParser)创建GenTokenParser,然后使用其lexeme字段。

答案 1 :(得分:2)

lexeme函数是GenTokenParser生成的makeTokenParser解析器记录的访问者,因此您需要将其应用于此类记录以获取它。一种常见的方法是使用记录通配符,例如

{-# LANGUAGE RecordWildCards #-}

import qualified Text.Parsec.Token as Tok

Tok.TokenParser { .. } = Tok.makeTokenParser {- language definition -}

这会将lexeme和所有其他解析器带入已应用于记录的范围,因此您可以像尝试一样使用它。