Синтаксические анализаторы. Нисходящие анализаторы
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