2013-05-06 2 views
1

От Text.Parsec.Token:Я не понимаю, как использовать функцию лексемы

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

Вероятно, что лексема принимает парсер р и обеспечивает анализатор, который имеет такое же поведение, как р, за исключением того, что она также пропускает все конечные пробелы. Верный?

Тогда как же следующее не работает:

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

Вы поняли документацию, то lexeme экспортируемые из Text.Parsec.Token представляет собой поле из GenTokenParser s u m, поэтому тип

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

и вы не снабжали GenTokenParser аргумент в lexeme constant.

Вам необходимо создать GenTokenParser от GenLanguageDef (обычно с makeTokenParser), чтобы использовать его поле lexeme.

2

Функция lexeme является аксессуаром в записи парсеров GenTokenParser, сгенерированной makeTokenParser, поэтому вам необходимо применить ее к такой записи, чтобы получить ее. Один из распространенных способов сделать это - использовать подстановочные знаки для записей, например.

{-# LANGUAGE RecordWildCards #-} 

import qualified Text.Parsec.Token as Tok 

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

Это принесет lexeme и все другие парсеры в рамки уже прикладывается к записи, так что вы можете использовать его, как вы пытаетесь сделать.

Смежные вопросы