Разбор избыточных скобок при восстановлении ввода в случае непредоставленной ошибки - PullRequest
4 голосов
/ 08 января 2020

Я написал анализатор в библиотеке Haskell parse c для lisp-подобного языка, и я хотел бы улучшить его сообщения об ошибках, но я застрял в следующей ситуации:

p :: Parser Integer
p = do
    try (string "number")
    space
    integer

parens :: Parser a -> Parser a
parens p = do
    char '('
    v <- p
    char ')'
    return v

finalParser p = p <|> (parens finalParser)

Таким образом, синтаксический анализатор p ведет себя довольно хорошо с ошибками, он не фиксирует и не использует ввод, пока не увидит ключевое слово "число". Как только он успешно проанализировал ключевое слово, он не восстановит свой ввод при неудаче. Если этот синтаксический анализатор объединяется с другими синтаксическими анализаторами с помощью оператора <|> и он анализирует ключевое слово, он покажет сообщение об ошибке p и не будет пытаться использовать следующий синтаксический анализатор.

Уже parens p больше не имеет этого свойства.

Я хотел бы написать функцию parens, как указано выше, которая потребляет только ввод, если анализатор p потребляет ввод.

Вот несколько примеров поведения, я пытаюсь достигать. finalParser должен проанализировать:

  1. "(((number 5)))", "number 5", "(number 5)" all должен проанализировать целое число 5 и потреблять все,
  2. "(5)" не должен ничего потреблять (даже скобки) и завершиться с ошибкой
  3. "(число ab c)", "число cde" должно завершиться с ошибкой и потреблять ввод.

1 Ответ

1 голос
/ 08 января 2020

Я хотел бы написать функцию parens, как указано выше, которая потребляет только ввод, если parser p потребляет ввод.

Вместо этого рассмотрите возможность синтаксического анализа вашего синтаксиса, чтобы вы даже не нужно возвращаться после использования скобок.

Вместо того, чтобы пытаться сделать эту работу:

parens p1 <|> parens p2

почему бы не написать это вместо этого:

parens (p1 <|> p2)

...