
- •2. Недетерминированный конечный автомат: формальное определение, построение множества достижимых состояний.
- •4. Преобразование недетерминированного конечного автомата в детерминированный.
- •6. Контекстно-свободные языки. Вывод. Дерево вывода.
- •8. Метод грамматического разбора сверху - вниз. Ll(1) – грамматики.
- •10. Левая факторизация.
- •12. Построение множества follow
- •14. Алгоритм работы таблично управляемого анализатора для ll(1) – грамматики.
- •32. Генератор компиляторов уасс. Использование неоднозначных грамматик.
- •18. Разбор методом «сдвиг – свертка» (shift – reduce) на основе стека.
- •24. Алгоритм заполнения таблиц разбора для slr (1) анализатора.
- •28. Построение абстрактного синтаксического дерева.
- •22. Каноническая совокупность множеств ситуаций.
- •34. Автомат с магазинной памятью. Допустимость по заключительному состоянию и по пустому магазину.
- •36. Lr(1) анализ. Lr(1)-ситуация. Замыкание множества ситуаций. Определение переходов.
- •16. Построение отношения предшествования операторов исходя из их ассоциативности и приоритета. Алгоритм разбора для грамматик простого предшествования.
- •38. Lalr(1) – грамматики. Построение lalr(1) – таблиц разбора.
- •1. Операции над языками. Регулярные выражения.
- •4) Положительное замыкание Клини (без пустой строки):
- •3. Преобразование регулярных выражений в недетерминированный конечный автомат
- •5. Минимизация детерминированного конечного автомата.
- •13. Построение таблицы разбора для ll(1) – грамматики
- •7. Контекстно-свободные грамматики для регулярных языков.
- •11. Построение множества first
- •9. Исключение левой рекурсии.
- •15. Грамматики простого предшествования. Использование отношения предшествования операторов
- •21. Алгоритм вычисления замыкания множества ситуаций (Closure).
- •17. Синтаксический анализ снизу – вверх. Основа. Подрезка основы.
- •19. Активный префикс. Обосновать, что основа всегда формируется в вершине стека.
- •27. Синтезируемые атрибуты. Их обработка в алгоритме сдвиг–свертка.
- •23. Переходы в slr (1) анализаторе. Функция goto. Допустимая ситуация.
- •29. Наследуемые атрибуты. Граф зависимостей.
- •25. Алгоритм lr – разбора.
- •33. Автомат с магазинной памятью. Графическое представление автомата с магазинной памятью. Вычислительный процесс в мп – автомате.
- •37. Lr(1) анализ. Заполнение таблиц lr-разбора
- •35. Типы и проверка типов.
- •26. Контекстно–зависимый анализ. Синтаксически управляемая трансляция.
11. Построение множества first
Множество First для нетерминала определяет множество терминалов, с которых может начинаться данный нетерминал.
1. Если х - терминал, то first(x)={x}. Так как первым символом последовательности из одного терминала может являться только сам терминал.
2. Если в грамматике присутствует правило Х , то множество first(х) включает . Это означает, что Х может начинаться с пустой последовательности, то есть отсутствовать вообще.
3. Для всех продукций вида XY1 Y2 … Yk выполняем следующее. Добавляем в множество first(Х) множество first(Yi) до тех пор, пока first(Yi-1) содержит , а first(Yi) не содержит . При этом i изменяется от 0 до k. Это необходимо, так как если Yi-1 может отсутствовать, то необходимо выяснить, с чего будет начинаться вся последовательность в этом случае.
9. Исключение левой рекурсии.
При процедуре рекурсивного разбора сверху вниз может возникнуть проблема бесконечного цикла.
В грамматике для арифметических операций применение второго правила приведет к зацикливанию процедуры разбора. Подобные грамматики называются леворекурсивными. Грамматика называется леворекурсивной, если в ней существует нетерминал А, для которого существует вывод А=>+А. В простых случаях левая рекурсия вызвана правилами вида
AA|
В этом случае вводят новый нетерминал и исходные правила заменяют следующими.
AB
BB|
(если есть нетерминал А, для которого существует вывод А→+А за 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 |
|
⋗ |
⋗ |
⋗ |
+ |
⋖ |
⋗ |
⋖ |
⋗ |
* |
⋖ |
⋗ |
⋗ |
⋗ |
$ |
⋖ |
⋖ |
⋖ |
|