Удаление левой рекурсии из грамматики без контекста - упорядочение непомощных
-
16-10-2019 - |
Вопрос
Недавно я внедрил алгоритм Паула для удаления левой рекурсии из грамматики без контекста:
Назначьте заказ $ a_1, dots, a_n $ неледиям грамматики.
за $ i: = 1 $ to $ n $, делайте начало
$ Quad $ за $ j: = 1 $ до i-1 $ do begin
$ Quad Quad $ для каждого производства формы $ a_i to a_j alpha $ do begin
$ Quad Quad Quad $ удалить $ a_i to a_j alpha $ из грамматики
$ Quad Quad Quad $ для каждого производства формы $ a_j to beta $ do begin
$ Quad Quad Quad Quad $ добавить $ a_i to beta alpha $ в грамматику
$ Quad Quad Quad $ End
$ Quad Quad $ End
$ Quad $ End
$ Quad $ Transform $ a_i $ -productions для устранения прямой левой рекурсии
конец
Согласно с этот документ, эффективность алгоритма решает, что зависит от упорядочения неледниц, выбранных в начале; В документе подробно обсуждается этот вопрос и предлагает оптимизации.
Некоторые обозначения:
Мы скажем, что символ $ x $ - это Прямой левый угол из непонмерального $ a $, если есть $ $-$-продукция с $ x $ в качестве самого левого символа с правой стороны. Мы определяем Отношение левого коря быть рефлексивным транзитивным закрытием отношения прямого левого углу, и мы определяем Надлежащее левое отношение быть переходным закрытием отношения с прямым левым углом. Непомонец есть оставил рекурсивный Если это правильный левый угол себя; Непомонец есть непосредственно оставил рекурсивным Если это прямой левый угол себя; и непонамер косвенно оставил рекурсивным Если он остается рекурсивным, но не остается непосредственно рекурсивным.
Вот что предлагают авторы:
Во внутреннем цикле алгоритма Паулла для непосмерлов $ a_i $ и $ a_j $, так что $ i> J $ и $ a_j $ - прямой левый угол $ a_i $, мы заменяем все случаи $ a_j $ как прямой Левый угол $ a_i $ со всеми возможными расширениями $ a_j $.
Это только способствует ликвидации левой рекурсии из грамматики, если $ a_i $ является левой рекурсивным, и $ a_j $ лежит на пути, который делает $ a_i $ левой рекурсивным; То есть, если $ a_i $ является левым углом $ a_j $ (в дополнение к $ a_j $ является левым углом $ a_i $).
Мы могли бы устранить замены, которые бесполезны при удалении левой рекурсии, если бы мы могли заказать непосродные грамматики, чтобы, если $ i> j $ и $ a_j $ - прямой левый угол $ a_i $, то $ a_i $ также является Левый угол $ a_j $.
Мы можем достичь этого, упорядочив не терминалы в порядке уменьшения количества отдельных левых углов, которые у них есть.
Поскольку соотношение левого коря является транзитивным, если C является прямым левым углом B, каждый левый угол C также является левым углом B.
Кроме того, поскольку мы определили, что отношение левого коря является рефлексивным, B является левым углом.
Следовательно, если C является прямым левым углом B, он должен следовать B в порядке уменьшения количества отдельных левых углов, если B не является левым углом C.
Все, что я хочу, - это знать, как заказать неледы вначале, но я не получаю его от бумаги. Может кто -нибудь объяснить это более простым образом? Псевдокод поможет мне лучше понять это.
Решение
Это на самом деле не очень сложно. Я предполагаю, что Epsilon Productions уже были исключены из языка, потому что это только скрывает ключевую концепцию «левого углу».
Сформируйте график g, где вершины-все не терминалы грамматики. Теперь нарисуйте направленное преимущество от A до B, если есть какое -либо производственное правило, которое выглядит как «a -> b [...]». В статье вызовы B A «прямой левый угол» A. В более общем плане, какой-то другой некомминальный C называется «левым углом» A, если есть какой-то путь от A до C вдоль краев этого графика. Это можно сделать путем вычисления Переходное закрытие G, назовите это H.
В документе предлагается заказать вершины, подсчитывая количество левых углов, которые имеет каждая вершина A (т.е. сколько других непомощных вы можете достичь от A, или вне степени A на графике H), затем сортируя их в порядке уменьшения по этому номеру.
Одна мотивация ручной волны для этой политики заключается в том, что если существует важный не концевой (скажем, начальные символы) с соединениями со многими другими символами), то имеет смысл очистить левую рекурсию от S До позже будет больше копий, которые вам нужно расширить. Я думаю, что объяснение в статье более убедительно, но, возможно, менее очевидное.