Россия |
Выбор инструкций при генерации кода
Представление выводов
Следующей нашей задачей будет построение множества выводов для данного дерева t в данной грамматике G .
Для представления множества выводов построим разметку C , которая вершине дерева v и нетерминалу K сопоставляет множество правил, каждое из которых начинает вывод образца t(v) из образца K в грамматике G (правило R начинает вывод образца t(v) из образца K тогда и только тогда, когда в множестве всех выводов t(v) из K DG (K,t(v)) существует вывод, который начинается тройкой (K, K, R) , т.е. применением правила R к единственной вершине, помеченной нетерминалом K .)
Построение выводов
Приведем алгоритм построения разметки C для грамматики в нормальной форме.
Данный алгоритм обходит дерево снизу-вверх. При этом он пытается применить все возможные правила к текущей вершине root. Если какое-либо правило R=N:p применимо, то в разметку для пары С[root][N] добавляется правило R .
Для того, чтобы проверить применимость правила для текущей вершины, проверяется соответствие этой вершины образцу в правой части правила (этим занимается функция Match ).
Кроме того, после вывода нового нетерминала в разметке C строится ее замыкание относительно цепных правил (это делает функция BuildClosure ).
Заметим, что формально говоря всегда можно рассматривать грамматики без цепных правил, поскольку любую грамматику можно преобразовать в эквивалентную, не содержащую цепных правил. Однако такое преобразование увеличивает число правил, в которых требуется нетривиальное сопоставление с образцом.
Построение выводов (продолжение)
Рассмотрим задачу сопоставления с образцом для вершины дерева (функция Match). Нас в данном случае интересуют образцы двух видов: лист, помеченный неким терминальным символом и дерево высоты один, корень которого помечен неким терминальным символом, а листья - нетерминалами. Кроме того, возможны образцы цепных правил, но они будут учтены при построении замыкания. Этим набором исчерпываются все образцы грамматики в нормальной форме.
Что касается образца первого вида, то данная вершина соответствует ему в том и только том случае, когда она является листом, помеченным тем же самым терминальным символом.
Для соответствия вершины образцу второго вида необходимо и достаточно, чтобы она была помечена нужным терминалом, а ее сыновья выводились в грамматике G из соответствующих нетерминалов образца. Поскольку построение разметки C происходит снизу-вверх, последнее условие может быть трактовано как непустота множества правил для данной вершины и данного нетерминала.
Наконец, функция BuildClosure, получая в качестве аргумента вновь выведенный нетерминал, строит замыкание разметки C относительно цепных правил, просто добавляя их в разметку для данной вершины и выведенного по цепному правилу нетерминала.