Опубликован: 23.07.2006 | Доступ: свободный | Студентов: 2215 / 889 | Оценка: 4.28 / 4.17 | Длительность: 21:37:00
Специальности: Системный архитектор
Лекция 6:

Синтаксические анализаторы. Нисходящие анализаторы

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

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 терминалами.

Пример.Рассмотрим грамматику с правилами:

{S \to aAS}
\\
{S \to b}
\\
{A \to a}
\\
{A \to bSA}

и два вывода

(1)	S =>* wSv => wuv =>* wx
(2)	S =>* wSv => wu1v =>* wy

Пусть цепочки x и y начинаются с a. Это означает, что в выводе участвовало правило S \to aAS . Следовательно, u = u1 = aAS . Пусть цепочки x и y начинаются с b . Это означает, что в выводе участвовало правило S \to 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
< Лекция 5 || Лекция 6: 123456 || Лекция 7 >