Парсек отрицательное совпадение - PullRequest
0 голосов
/ 26 января 2019
parseIdent :: Parser (String)
parseIdent = do
  x <- lookAhead $ try $ many1 (choice [alphaNum])
  void $ optional endOfLine <|> eof
  case x of
    "macro" -> fail "illegal"
    _ -> pure x

Я пытаюсь проанализировать буквенно-цифровую строку, которая завершается успешно, только если она не соответствует заранее заданному значению (macro в данном случае).


Однако следующее дает мне ошибку:

*** Exception: Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string.

Что не имеет смысла, как many1 (choice [alphaNum]) принимает пустую строку?


Эта ошибка исчезнет, ​​если я удалю lookAhead $ try. Но это «не получается» с illegal:

...
*** Exception: (line 6, column 36):
unexpected " "
expecting letter or digit or new-line
illegal

Правильно ли я поступаю? Или есть другой метод для осуществления отрицательного поиска?

1 Ответ

0 голосов
/ 26 января 2019

У вас почти есть это:

import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.String
import Control.Monad

parseIdent :: Parser (String)
parseIdent = try $ do
  x <- many1 alphaNum
  void $ optional endOfLine <|> eof
  case x of
    "macro" -> fail "illegal"
    _ -> pure x

Итак, почему ваш код не работал?

  • try находится не в том месте. Реальный откат назад - это откат после того, как вы вернули свое буквенно-цифровое слово и проверили, что это не "macro"
  • lookAhead не имеет здесь никакого дела. Если вы в конечном итоге получили нужное слово, вы do хотите, чтобы слово использовалось на входе. try уже позаботится о сбросе вашего входного потока в его прежнее состояние
...