Комментарии 6
Спасибо за статью. По-моему, у вас получилось довольно хорошее объяснение нисходящего разбора. Ожидал увидеть в статье отсылки к парсер-комбинаторам, потому что их идея очень близка: там парсер — это что-то, что может "откусить" префикс строки и выдать результат и оставшуюся строку, но их ещё и комбинируют, чтобы из простых парсеров (база — один токен) получать более сложные (вплоть до парсера всего языка).
Не увидел в статье терминов LL(1) и LL(*), а ведь первый значительно проще и быстрее. Подходит для простых языков.
Во-первых, LL-анализ и анализ методом рекурсивного спуска это не одно и то же. Классически, LL-анализ чисто предиктивный, то есть без возвратов. А анализ методом рекурсивного спуска запросто может быть с возвратами. Вы по сути реализовали вариант с возвратами, так что LL тут вообще-то немного ни при чём — это при том, что Ваша грамматика навскидку принадлежит LL(1).
А во-вторых, обработка ошибок разбора у Вас конечно совсем никакая, и никаких гарантий, что при успешном разборе на вход был подан синтаксически корректный текст у Вас нет, в отличие от нормальных анализаторов.
Даже как объяснение "на пальцах" Ваш подход как-то не очень, фишка LL(k) анализа таки как раз в том, что ему не нужно забегать вперёд и искать скажем там парную закрывающую фигурную скобку, за счёт чего достигается линейная скорость разбора. А у Вас ассимптотика в худшем случае квадратичная навскидку (по крайней мере если допустить что значение само может быть набором пар ключ-значение)
Самое, конечно, главное уточнение — что LL(...) и рекурсивный спуск — это не одно и то же. Мне они представлялись почти синонимами, а это не так.
Про LL-парсинг: Подход к синтаксическому анализу через концепцию нарезания строки