Я написал анализатор в библиотеке 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 должен проанализировать:
- "(((number 5)))", "number 5", "(number 5)" all должен проанализировать целое число 5 и потреблять все,
- "(5)" не должен ничего потреблять (даже скобки) и завершиться с ошибкой
- "(число ab c)", "число cde" должно завершиться с ошибкой и потреблять ввод.