Ограничения парсеров LL vs LR?
Я знаю основные различия парсеров LL vs LR. Я также знаю, что GLR, SLR и LALR являются расширениями парсеров LR. Поэтому мой вопрос более подробно...
учитывая парсер LL(*) и любую вариацию парсера LR, есть ли какой-либо язык, который можно описать в одном, а не в другом? Или, проще говоря, есть ли какая-либо особенность или свойство, которые не могут быть выражены ни с тем, ни с другим?
в качестве конкретного примера. Если я должен был создать язык с помощью парсера LL (*), я буду когда-либо сталкивались с желаемой функцией/свойством, которое я мог бы добавить к своему языку, что было бы возможно только с помощью парсера LR (или наоборот)?
6 ответов
конечно. Синтаксические анализаторы LL не могут обрабатывать грамматики с левой рекурсией. L(AL)R (k) Парсеры для фиксированного k не смогут проанализировать некоторые вещи, которые LL (*) парсер может обрабатывать, потому что k
вот несколько частей мнения, вы можете рассмотреть их точку и контрапункт:
- разбор должен быть проще - в пользу LL
- почему я предпочитаю Парсеры LALR - в пользу LR
вы можете найти интересный этот абзац в Википедии, в котором говорится, что ll (*) грамматики являются подмножеством LR (k) грамматик: http://en.wikipedia.org/wiki/Context-free_grammar#Restrictions Таким образом, вы можете анализировать больше языков, используя методы анализа LR.
есть некоторые грамматики, которые не могут быть "переписаны" для анализа парсерами LL, которые могут быть проанализированы парсерами LR. Один пример: Дана простая грамматика, которая строит термины с подстроками:
S -> S - S | num
у вас, очевидно, есть левая рекурсия здесь, которая не может быть обработана ll-парсерами. Чтобы сделать эту грамматику разборной по LL, вы должны устранить левую рекурсию:
S -> num S'
S' -> - num S' | epsilon
теперь ваш парсер LL может обрабатывать эту грамматику. Но при создании синтаксического дерева для такой термин, как 4 - 2 -1, глубинный поиск, выполняемый на дереве, даст вам 4-(2-1) = 3 вместо (4 - 2) - 1 = 3, Как вы ожидаете.
причина этого в том, что вы должны использовать лево-рекурсивные правила в своей грамматике для обработки лево-ассоциативных операторов (например, substract). Но лево-рекурсивные правила не могут обрабатываться ll-парсерами.
Итак, здесь у вас есть класс языков, которые не могут быть обработаны LL.
парсер LR может принимать больший класс языков, чем LL. В LL(k) и LR(k) k означает количество символов lookahead, которые ему необходимо знать, чтобы он мог применять соответствующее производство/сокращение. Чем больше K, тем больше таблицы синтаксического анализа. Таким образом, k не ограничивает только Парсеры LR, он также ограничивает Парсеры LL. Причина, по которой парсер LR может принимать больший класс языков, заключается в левой рекурсии, которая проблематична при работе с парсерами LL. Но это не совсем так, потому что прямая рекурсия разрешима, что означает, что вы можете переписать грамматику, чтобы быть грамматикой LL. Прямая Рекурсия-это что-то вроде A - > Abc. Когда у вас есть косвенная рекурсия, для которой вы теперь, вероятно, знаете, как это выглядит, тогда у вас есть проблема. Парсеры LR могут решить эти проблемы, потому что они делают дерево синтаксического анализа снизу вверх. Вам придется заглянуть немного глубже в анализ LR, чтобы понять, почему это именно так. Но Парсеры LR не все могущественны, у них тоже есть ограничения. Некоторые грамматики очень трудно переваривается и K фактор не помогает. Для такого рода грамматик необходим парсер GLR, который фактически имитирует парсер LR(k), но использует обратное отслеживание для анализа всего пространства синтаксического анализа при возникновении неоднозначности производства/сокращения.
ll синтаксический анализ теоретически O(n^4), или довольно медленно. Разбор LR быстрее, O(n^3) или довольно медленный. https://en.wikipedia.org/wiki/Top-down_parsing
хотя я хотел бы увидеть доказательство этого.