2013-05-06 51 views
1

Text.Parsec.Token我不明白如何使用语义功能

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

看来,语义需要一个解析器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 

我在做什么错?

回答

6

你误解了这个文件,从Text.Parsec.Token出口的lexemeGenTokenParser s u m的领域,所以类型是

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

和你没有lexeme constant提供的GenTokenParser说法。

您需要先创建GenLanguageDef(通常为makeTokenParser)的GenTokenParser首先使用其lexeme字段。

2

lexeme函数是由makeTokenParser生成的解析器记录的一个访问器,因此您需要将它应用于这样的记录才能得到它。一种常见的做法是使用记录通配符,例如

{-# LANGUAGE RecordWildCards #-} 

import qualified Text.Parsec.Token as Tok 

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

这将带来lexeme和所有其他解析器进入活动范围已经申请到了创纪录的,所以你可以使用它就像你试图做。