Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпоры_по тяпу готовые.doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
952.32 Кб
Скачать

11. Построение множества first

Множество First для нетерминала определяет множество терминалов, с которых может начинаться данный нетерминал.

1. Если х - терминал, то first(x)={x}. Так как первым символом последовательности из одного терминала может являться только сам терминал.

2. Если в грамматике присутствует правило Х , то множество first(х) включает . Это означает, что Х может начинаться с пустой последовательности, то есть отсутствовать вообще.

3. Для всех продукций вида XY1 Y2 … Yk выполняем следующее. Добавляем в множество first(Х) множество first(Yi) до тех пор, пока first(Yi-1) содержит , а first(Yi) не содержит . При этом i изменяется от 0 до k. Это необходимо, так как если Yi-1 может отсутствовать, то необходимо выяснить, с чего будет начинаться вся последовательность в этом случае.

9. Исключение левой рекурсии.

При процедуре рекурсивного разбора сверху вниз может возникнуть проблема бесконечного цикла.

В грамматике для арифметических операций применение второго правила приведет к зацикливанию процедуры разбора. Подобные грамматики называются леворекурсивными. Грамматика называется леворекурсивной, если в ней существует нетерминал А, для которого существует вывод А=>+А. В простых случаях левая рекурсия вызвана правилами вида

AA|

В этом случае вводят новый нетерминал и исходные правила заменяют следующими.

AB

BB|

(если есть нетерминал А, для которого существует вывод А→+А за 1 или более шагов). Левой рекурсии можно избежать, преобразовав грамматику.

Например, продукции A→A

│β

Можно заменить на эквивалентные:

A→ β В

В→  В

│ ε

Для такого случая существует алгоритм, исключающий левую рекурсию:

1) определяем на множестве нетерминалов какой-либо порядок (А1, А2, …, Аn)

2) берем каждый нетерминал, если для него есть продукция, учитывающая нетерминал, стоящий левее, и преобразуем грамматику:

for i:=1 to n do

for j:=1 to i-1 do

if Ai → Ajγ then Ai→δ1γ

│ δ2γ

│ δkγ, где

Aj → δ1│ δ2│ …│ δk

3) исключаем все случаи непосредственной левой рекурсии (правило1)

Т.о. алгоритм помогает избежать зацикливания.

Общий вид правила исключения левой рекурсии

A → A α1

| A α2

...

| A αM

| β1

| β2

...

| βN

A → β1 A´

| β2 A´

...

| βN A´

A´ → α1 A´

| α2 A´

...

| αM A´

| ε

15. Грамматики простого предшествования. Использование отношения предшествования операторов

Грамматики простого предшествования отличаются следующим:

1) у них нет продукций, имеющих в правой части .

2) нет продукций, в которых два нетерминала стоят рядом.

Грамматики, удовлетворяющие второму требованию, называются операторными.

Например: E → EAE | (E )| -E | id

A → + | - | * | / | ^

можно преобразовать к операторному виду:

E → E+E | E-E | E*E | E/E | E^E | (E) | -E | id

Для нее на основе предшествующих операций можно строить дерево разбора. Для этого необходимо задать три отношения предшествования; на их основе можно выделить формы отношений:

a ⋖ b - a уступает b

a ≐ b - a имеет одинаковый приоритет с b

a ⋗ b - a имеет приоритет над b

Эти операции имеют значение, отличное от арифметических, например, истинно a ⋖ b и b ⋖ a. Для некоторых нетерминалов могут вообще не выполняться такие операции. Отношение предшествования можно задать в форме таблицы, при помощи которой можно легко находить основы

id+id+id: $<• id•>+<•id•>*<•id•>$

Основы получаются: цепочка просматривается до знака •> метка идем обратно до знака <• метка. Между метками будет основа. Когда свернем эти основы, получим: Е+Е*Е. Нетерминалы нужны только для генерации результирующего кода.

Получим последовательность: + *.

 

id

+

*

$

id

 

+

*

$

 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]