Почему существуют парные анализаторы LR (0), но не LL (0)?

Я читал и в Википедии, и заметил, что хотя существуют парсеры LR (0), не существует парсера LL (0).

Из того, что я читал, я понимаю, что k в LL (k)/LR (k) означает, сколько символов синтаксический анализатор может видеть вне текущего символа, над которым он в настоящее время работает.

Итак, мой вопрос: почему нет такого понятия, как LL (0) парсер, хотя существует LR (0)?

Ответ 1

Разница связана с тем, что k означает в LR (k) по сравнению с LL (k).

В LL (k) синтаксический анализатор поддерживает информацию о синтаксисе сверху вниз, слева направо, в котором прослеживается самый левый вывод. Парсер работает, повторно просматривая текущий нетерминальный символ, затем проверяя следующие k токенов входного потока, чтобы определить, какое производство следует использовать. В результате, если у вас есть парсер LL (0), анализатор должен будет предсказать, какую продукцию использовать, основываясь исключительно на текущем нетерминале. Это возможно только в том случае, если у каждого нетерминала есть только одно связанное с ним производство, а это означает, что грамматика генерирует ровно одну строку или вообще не имеет нити (путем перехода в цикл). Поэтому, хотя он математически хорошо определен, анализ LL (0) никогда не используется на практике.

В LR (k) синтаксический анализатор работает снизу вверх. Он поддерживает стопку символов вместе с текущим "состоянием" и затем постоянно решает, выполнять ли сдвиг (нажатие другого символа поверх стека) или уменьшить (выбирая некоторое количество символов из стека и применяя производственную в обратном порядке). Одним из ключевых различий между парсером LL (k) и LR (k) является то, как парсер LR (k) решает, какое действие выполнить. В парсере LR (k) решение о том, что делать дальше s, основывается как на следующих k токенах lookahead, так и на текущем состоянии анализатора. В результате LR (0) синтаксический анализатор все же может принимать несколько разумные решения о том, какое действие нужно выполнить, даже если оно не может видеть никаких токенов, поскольку текущее состояние анализатора может кодировать огромное количество информации о том, где в произведении парсер и что он может реально ожидать см. в качестве следующих токенов ввода (даже если анализатор не может напрямую смотреть на эти токены).

Короче говоря, LL (0) крайне слаб, потому что парсер должен чисто основывать свое решение на текущем нетерминале, что означает, что он не может принимать одно из многих различных действий, основанных на том, какое производство может быть использовано. Парсер LR (0) достаточно эффективен, потому что парсер основывает свой выбор на своем внутреннем состоянии, что обычно достаточно подробно, чтобы парсер принимал обоснованные решения о том, что делать дальше.

Есть еще одна причина, когда LL (0) слаба, а LR (0) достаточно мощная. В парсере LL (0) синтаксический анализатор должен немедленно решить, какие производственные операции должны выполняться, а это значит, что анализатор должен полностью отследить производственные процессы. В анализаторе LR (0) анализатор может сместить несколько символов, прежде чем принимать решение о том, что пришло время уменьшить. Следовательно, синтаксический анализатор без каких-либо взглядов может отложить принятие решения о том, какое сокращение использовать до тех пор, пока оно не увидит достаточно токенов ввода, чтобы получить смысл для структуры строки. Это частный случай более общего факта, что любая грамматика LL (k) автоматически LR (k).

Надеюсь, это поможет!