Почему "between (char '"') (char '"') (many charLiteral)" не работает для синтаксического анализа строковых литералов? - PullRequest
4 голосов
/ 06 мая 2020

В документации для Text.Megaparsec.Char.Lexer.charLiteral предлагается использовать char '"' *> manyTill charLiteral (char '"') для синтаксического анализа строковых литералов (где manyTill определено в модуле Control.Applicative.Combinators в библиотеке parser-combinators).

Однако Control.Applicative.Combinators также определяет between, который, насколько я понимаю, должен делать то же самое, что и предложение выше, когда используется так: between (char '"') (char '"') (many charLiteral).

Однако использование парсера between выше делает не работает для синтаксического анализа строковых литералов - ошибка " неожиданный конец ввода. ожидает '"' или буквенного символа"(что означает, что конечная кавычка никогда не обнаруживается). Почему бы и нет?

Кроме того, в более общем плане, почему between pBegin pEnd (many p) не эквивалентно pBegin *> manyTill p pEnd?

1 Ответ

7 голосов
/ 06 мая 2020

between l r m не делает ничего впечатляющего, на самом деле он просто пытается l, затем m, затем r и возвращает результат m. Итак, в between (char '"') (char '"') (many charLiteral) many charLiteral не знает, что он не должен потреблять ". many просто продолжает потреблять все, что принимает синтаксический анализатор аргументов ... что, поскольку charLiteral просто принимает все, , означает, что он перемешивает все до конца ввода. У второго char '"' нет способа остановить это, ему просто нужно обойтись тем, что осталось ... т.е. сбой , потому что там это ничего не осталось!

Напротив, manyTill на самом деле проверяет, совпадает ли «до», и только применяет каждую итерацию анализатора контента, когда это не так. Следовательно, завершающий " не передается в charLiteral, и вы получаете желаемое поведение.

...