Россия |
Синтаксические анализаторы. Нисходящие анализаторы
LL(k)-грамматика
Определение.Грамматика G = (VT, VN, P, S) называется LL(k)-грамматикой, если для любых двух левых выводов
S =>* wAv => wuv =>* wx S =>* wAv => wu1v =>* wy,
для которых FIRST k (x) = FIRSTk (y) верно, что u=u1 .
То есть если для данной цепочки wAv , состоящей из терминальных и нетерминальных символов и k первых символов (если они есть), выводящихся из Av , существует не более одного правила, которое можно применить к A , чтобы получить вывод какой-нибудь терминальной цепочки, начинающейся с w и продолжающейся упомянутыми k терминалами.
Пример.Рассмотрим грамматику с правилами:
и два вывода
(1) S =>* wSv => wuv =>* wx (2) S =>* wSv => wu1v =>* wy
Пусть цепочки x и y начинаются с a. Это означает, что в выводе участвовало правило . Следовательно, u = u1 = aAS . Пусть цепочки x и y начинаются с b . Это означает, что в выводе участвовало правило . Следовательно, u = u1 = b .
Для выводов
(3) S =>* wAv => wuv =>* wx (4) S =>* wAv => wu1v =>* wy
рассуждение аналогично. Таким образом, грамматика обладает свойством LL(1).
Для LL(1)-грамматик может быть построен анализатор методом рекурсивного спуска без возвратов.
Пример
Пример
(1)S -> if S then S else S (2)S -> begin S L (3)S -> print E (4)L -> end (5)L -> ; S L (6)E -> num = num
Для этой LL (1)-грамматики построим анализатор методом рекурсивного спуска.
Рассмотрим грамматику:
(1) S -> if E then S else S (2) S -> begin S L (3) S -> print E (4) L -> end (5) L -> ; S L (6) E -> num = num
Напишем анализатор языка, порождаемого этой грамматикой, методом рекурсивного спуска. Для этого нам придется описать по одной процедуре для каждого нетерминала грамматики.
class SimpleParser { /* Лексические классы, т.е. терминалы */ const int IF = 1; const int THEN = 2; const int ELSE = 3; const int BEGIN = 4; const int END = 5; const int PRINT = 6; const int SEMICOLON = 7; const int NUM = 8; const int EQ = 9; public static void nextStep(int lc) { if (lexical_class == lc) lexical_class = getLC(); else error(); } public static void S(void) { switch(getLC()) { case IF: E(); nextStep(THEN); S(); nextStep(ELSE); S(); break; case BEGIN: S(); L(); break; case PRINT: E(); break; default: error(); break; } } public static void L(void) { switch (lexical_class) { case END: getLC(); break; case SEMICOLON: getLC(); S(); L(); break; default: error(); break; } } public static void E(void) { nextStep(NUM); nextStep(EQ); nextStep(NUM); } public static void main(void) { lexical_class = getLC(); S(); } } // end of SimpleParser