Реферат Курсовая Конспект
РЕКУРСИВНЫЙ СПУСК - раздел Программирование, СИНТАКСИЧЕСКИЙ И СЕМАНТИЧЕСКИЙ АНАЛИЗ Рассмотрим Подкласс Кс-Грамматик - S-Грамматики Определение ...
|
Рассмотрим подкласс КС-грамматик - S-грамматики
Определение 5.2. S-грамматики — это подкласс контекстно-свободных грамматик, таких что:
1. Правая часть каждого правила начинается с терминала.
A ® ab | ba
2. Если в грамматике есть альтернативные правила, то они обязательно начинаются с разных терминальных символов
A ® ab | ba, причём a ¹ b.
S-грамматики часто называют разделёнными или простыми.
Пример 5.3. G[S]:
1. S ® aT
2. S ® TbS
3. T ® bT
4. T ® ba
G[S] не является S-грамматикой, так как в правиле 2 первый символ — нетерминальный, а это противоречит условию 1 для S-грамматик. Также 3 и 4 правила не удовлетворяют условию 2, так как два альтернативных правила начинаются с одного терминального символа.
Пример 5.4. G’[S]:
1. S ® abR
2. S ® bRbS
3. R ® a
4. R ® bR
G’[S] — удовлетворяет всем условиям и является S-грамматикой.
Анализ S-грамматик весьма эффективен методом рекурсивного спуска.
Метод рекурсивного спуска. Основная идея метода рекурсивного спуска состоит в том, что каждому нетерминалу грамматики ставится в соответствие определённая программная единица, процедура или функция (например в языке С — функция), которая распознаёт цепочку, порождаемую этим нетерминалом. Эти процедуры (функции) вызываются в соответствии с правилами грамматики, причём иногда вызывают сами себя рекурсивно. Следовательно, языком реализации этого метода, может быть лишь такой язык, который допускает рекурсию.
Пример 5.5. G[S]:
1. S ® aAS
2. S ® b
3. A ® cASb
4. A ® L
Легко видеть, что G[S] —S - грамматика. Приведем анализ G[S] методом рекурсивного спуска (рис. 5.18.).
Корневой сегмент | Процедура S | Процедура A | |
“Начало” Установим вход = первый входной символ; S; Если вход ¹ то ERROR; Иначе STOP; /* — признак окончания программы */ | Переход по символу: | Переход по символу: | |
Символ | Метка | Символ | Метка |
a | M1 | a | M4 |
b | M2 | b | M4 |
c | ER | с | M3 |
ER | ER | ||
Другой | ER | Другой | ER |
M1: Scan; A; S; Возврат; M2: Scan; Возврат; ER: ERROR; Возврат; | M3: Scan; A; S; Если вход ¹ ‘b’ то ERROR; Иначе Scan; Возврат; M2: Возврат; |
Рис. 5.18. Алгоритм работы функции
На рис. 5.18. проиллюстрирован алгоритм работы функции (нетерминалов) A, S и корневого сегмента на некотором псевдоязыке. В соответствии с правилами 1, 2 грамматики G[S] процедура S должна начинаться с терминалов a или b и не может начинаться с терминалов c или , поэтому переход по этим символам влечёт ошибку, то есть переход на метку ERROR.
Приведем еще пример реализации метода рекурсивного спуска для грамматики “инструкция”
G[<инструкция>]
1. <инстр> ® <пер> = <выр> |
IF <выр> THEN <инстр> [ ELSE <инстр> ]
2. <пер> ® i[(<выр>)]
3. <выр> ® T{+T}
4. T ® O{*O}
5. O ® <пер> | (<выр>)
По классификации Хомского легко показать, что G[<инстр>] является контекстно-свободной и разделённой, то есть грамматикой типа LL(1) (LastLeft — самый крайний левый символ). В общем случае рассматривают грамматики LL(К), в которых по К левым символам определяется принадлежность цепочки к соответствующему правилу грамматики. Грамматики этого класса удовлетворяют главному критерию однозначности и безвозвратности разбора. Эти грамматики также как и S-грамматики эффективно анализировать методом рекурсивного спуска. Учитывая выше приведённый алгоритм рекурсивного спуска, покажем реализацию синтаксического процессора методом рекурсивного спуска на Алголоподобном языке с принятыми следующими допущениями:
1) Переменная nx (от слова next) всегда содержит очередной символ, по которому определяется альтернативами LL(1) - грамматики.
2) scan готовит очередной символ исходной программы и помещает его в nx.
3) error процедура, обрабатывающая ошибки синтаксиса (управление передаётся в вызывающую программу).
Следуя методу рекурсивного спуска, все нетерминалы грамматики G[<инстр>] обозначим своими процедурами, несущими туже аббревиатуру, что и нетерминалы.
instr /* <инстр> */
{
if (nx=“IF”) then
begin
scan;
expr;
if (nx!=“THEN”) then
error;
else
begin
scan;
instr;
if (nx=“ELSE”) then
begin
scan;
instr;
end;
end;
end;
else
begin
var;
if (nx!=“=”) then
error;
else
begin
scan;
expr;
end;
end;
}
/*---------------------------------------------------------------------*/
var /* <пер> */
{
if (nx!=“i”) then error;
else
begin
if (nx!=“(”) then
begin
scan;
expr;
if (nx!=“)”) then error;
else scan;
end;
end;
}
/*---------------------------------------------------------------------*/
expr /* <выр> */
{
t;
while (nx=“+”) do
begin
scan;
t;
end;
}
/*---------------------------------------------------------------------*/
t /* Т */
{
o;
while (nx=“*”) do
begin
scan;
o;
end;
}
/*---------------------------------------------------------------------*/
o; /* O */
{
if (nx=“(”) then
begin
scan;
expr;
if (nx!=“)”) then error;
else scan;
end;
else var;
}
– Конец работы –
Эта тема принадлежит разделу:
На сайте allrefs.net читайте: "СИНТАКСИЧЕСКИЙ И СЕМАНТИЧЕСКИЙ АНАЛИЗ"
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: РЕКУРСИВНЫЙ СПУСК
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов