
3 Контекстовільні мови
3.1 Дерева розбору
Домовимося далі для позначення терміналів використовувати малі букви з початку алфавіту (такі, як a, b, c), символи, цифри, рядки, виділені жирним шрифтом (такі, як id, if). Нетермінали будемо позначати великими буквами з початку алфавіту (A, B, C), рядками, виділеними курсивом (stmt, expr). Великі букви з кінця алфавіту (X, Y, Z) будуть позначати граматичні символи, тобто або термінали, або нетермінали. Малі букви з кінця алфавіту (u, v, ... , z) – рядки терміналів. Малі грецькі букви (такі, як α, β, γ) будуть представляти рядки граматичних символів.
Візьмемо граматику для побудови виразів типової мови програмування. Обмежимося операторами “+”, “*”, а як аргументи візьмемо ідентифікатори, що починаються символами а або b, а далі йде ланцюжок з а,b,0,1.
Граматика може мати вигляд G=({E,I}, T, P, E), де
T={+, *, (, ), a, b, 0, 1}, а P – множина продукцій:
E → I , I → B,
E → E + E , I → Ia,
E → E * E, I → Ib,
E → (E), I → I0,
I → a, I → I1.
Надалі нетермінали будемо називати також змінними.
Для обмеження числа виборів у процесі породження будемо заміняти крайню ліворуч змінну тілом її продукції.
E
E * E
I * E
a * E
a * (E)
a *(E + E) a * (I + E) a * (a + E)
a * (a + I) a* (a + I0) a * (a + b0) .
Таке
породження будемо називати лівим і
позначати через
,
від слова leftmost (зліва).
Аналогічно
будуються праві породження, що позначаються
через
,
від слова rightmost (справа).
E E * E E *(E) E *(E + E)
E * (E + I) E * (E + I0) E *(E + b0)
E * (I + b0) E *(a + b0) a * (a + b0).
Будь-яке породження має еквівалентні ліве і праве породження.
Приклад виконання завдання. Є граматика з продукціями
S → if E then S else S | if E then S | other .
Показати, що ланцюжок
if E then if E then other else other
має два лівих породження.
Перше породження має вигляд:
S if E then S else S if E then if E then S else S
if E then if E then other else S
if E then if E then other else other.
Друге породження має вигляд:
S if E then S if E then if E then S else S
if E then if E then other else S
if E then if E then other else other.
Наступним важливим поняттям є дерева розбору.
Будемо розглядати граматику
G= (V, T, P, S).
Дерева розбору для G – це дерева з такими властивостями.
1 Кожен внутрішній вузол позначений змінною з множини V.
2 Кожен лист позначений змінною або терміналом, або ε.
3 Якщо дочірні вузли вузла A позначені зліва направо X1, X2, … , Xk , то A → X1 X2 … Xk є продукцією в P.
Якщо подивитися на листи дерева розбору і виписати їх позначення зліва направо, одержимо ланцюжок, що називається кроною дерева і завжди є ланцюжком, виведеним зі змінної, яка позначає корінь.
Особливий інтерес становить дерево, корінь якого відмічений стартовим символом, а крона є термінальним ланцюжком.
Дерево розбору для попереднього прикладу зображене на рис. 3.1.