- •Цель лабораторных работ:
- •Лабораторная работа № 1 разработка грамматики заданного языка.
- •Краткие теоретические сведения
- •Формы записи грамматики
- •Порядок выполнения работы
- •Требования к оформлению отчета
- •Основные контрольные вопросы
- •Лабораторная работа № 2 работа с таблицей символов Проектирование лексического анализатора
- •Краткие теоретические сведения
- •Требования к оформлению отчета
- •Основные контрольные вопросы
- •Лабораторная работа № 3 Синтаксический и семантический анализ. Построение простейшего дерева вывода
- •Краткие теоретические сведения
- •Порядок выполнения работы
- •Требования к оформлению отчета
- •Основные контрольные вопросы
- •Лабораторная работа № 4 Генерация и оптимизация объектного кода
- •Краткие теоретические сведения
- •1 Алгоритм генерации объектного кода по дереву вывода
- •Построение ассемблерного кода по дереву вывода
- •Построение списка триад по дереву вывода.
- •Оптимизация объектного кода методом свертки
- •Оптимизация объектного кода методом исключения лишних операций
- •Общий алгоритм генерации и оптимизации объектного кода
- •Порядок выполнения работы
- •Требования к оформлению отчета
- •Основные контрольные вопросы
- •Варианты заданий
- •Рекомендуемая литература
Лабораторная работа № 1 разработка грамматики заданного языка.
Цель работы: изучение основных понятий теории регулярных грамматик, регулярных выражений, получение практических навыков обобщения набора ситуаций, формальной записи грамматики на одном из способов описания синтаксиса языка (Форма Бэкуса-Наура, например) и использования регулярных выражений.
Для выполнения лабораторной работы требуется разработать грамматику языка, пример которого есть в варианте задания. Записать разработанную грамматику на формальном языке - Форма Бэкуса-Наура или расширенная форма Бэкуса-Наура.
Краткие теоретические сведения
Нетерминальные символы (нетерминалы) несут смысловое содержание. Каждый нетерминал обозначает конкретную конструкцию языка. Напрмер, нетерминал <Число> обозначает синтаксическую конструкцию языка, состоящую из цифр, знака, точки, расположенных в строго заданном порядке правилом грамматики.
Обозначаются нетерминалы печатными прописными буквами латинского алфавита и/или заключаются в угловые скобки.
<...> — нетерминальный символ
A, ..., Z — нетерминальные символы
Примеры: F FF , ALFA, <нетерминал> , A1 , <Coshy>
От изменения обозначений нетерминальных символов грамматика не изменяется. Нетерминалы являются связующими элементами грамматики и поэтому их обозначение выбирается произвольно автором грамматики так, чтобы смысловая нотация грамматики была предметно понятна и читабельна. Так, если разрабатывается грамматика числовой константы , то понятно, что одним из нетерминальных символов в этой грамматике будет нетерминал <числовая константа>, который можно обозначить и сокращённо <ЧК> или просто ЧК, но при этом сокращения менее читабельны и осложняют понимание грамматики, т.к. в принятых соглашениях ЧК можно прочитать как два нетерминала.
Терминальные символы (терминалы) являются субъектами языка, их можно назвать буквами языка, порождаемого грамматикой. Из этих букв состоят слова, или цепочки, языка. Обозначаются терминалы строчными буквами латинского алфавита или клавиатурными аббревиатурами:
a,..., z — формальные обозначения терминальных символов;
Примеры: а, = , ** - знак возведения в степень в языке FORTRAN,
If , WHILE , DO и т.д.- группа кючевых слов
Редукция (в литературе также встречается Продукция) – правило вывода.
<A> ® <B> — из нетерминала A выводится (следует) нетерминал B,
( ® эквивалентно ::= )
Операция ‘или’ обозначается знаком ‘ |’
а | b — терминал a или терминал b
Пустой символ - . Часто употребляется в литературе также L или µ. Пусто – L, или , или µ, - операция для организации механизма умолчания и других.
Псевдооперация умолчания - […]
[a] — по определению есть a | L - обозначает, что а может быть, а может и не быть
Итерация – {…}
{a} — по определению есть a | aa | ... | a...a |L
означает, что a может встречаться в цепочке символов 1,2,...n ‘n’ число раз, либо вообще не встречаться
{a}k — аналогично, но n не превышает значение k (n<=k).
Если {} или [] являются элементами алфавита какого-то языка, то чтобы отличить конструкцию от алфавита, скобки подчёркивают.
Соглашения
Б — A|B|...|Z, a|b|...|z - это буквы, которые являются терминальным символом из словаря латинского алфавита. Вместе с русской аббревиатурой Б для обозначения класса букв договоримся также использовать латинскую аббревиатуру LT (LetTer).
Ц — 0|1|...|9 – это терминальный символ цифрового регистра. Здесь также договоримся употреблять латинское обозначение для класса цифр – DT ( DigiT).
<идентификатор> -- это ещё одна из часто употребляемых конструкций. Договоримся обозначать эту конструкцию(токен) русской аббревиатурой ИД или латинской - id.
Все обозначения множеств будем выделять жирно.
Словарь (алфавит) — конечное непустое множество символов. Словарь обозначается заглавными прописными буквами латинского алфавита жирно, чаще - V и S (возможно с индексами).
Термин алфавит как класс или группа символов введён для обозначения например букв русского [А,Б, …Я] или латинского [A,B, …Z] алфавитов соответственно как прописных так и строчных. В теории формальных языков эта категория приняла лишь более строгую и конкретную форму.
Пример: A={a, b}, словарь А состоит из двух терминалов a, b.
B= {0,1}- бинарный словарь
ASCII и EBCDIC – являются примерами компьютерных алфавитов
Отметим, что формальный словарь, о котором в данном случае идёт речь, необязательно должен состоять только из терминальных символов. В общем случае, как будет показано ниже, общий словарь V включает как терминальные, так и нетерминальные символы.
Цепочки (строки, слова) — конечная последовательность элементов словаря. Обозначаются строки греческими прописными буквами - , , γ, ...
Пример: = aa, = abc
Длина цепочки – обозначается модулем | … |
Пример: || = 2 — длина цепочки.
|L| = 0, || = 3.
Конкатенация цепочек — присоединение цепочки. Это основная операция над цепочками
Пример: = ab, = cab, тогда = abcab.
γ = L, тогда γ = ab.
Операция коммутативности над цепочками не выполняетсяв общем случае. Действительно, если = ab, = cab, то = abcab, но это не одно и то же, что и , т.к. = cabab.
Грамматикой G[Z] называется конечное непустое множество правил вывода, множества терминальных символов (терминальный словарь), множества нетерминальных символов и начального символа Z , который должен встречаться хотя бы один раз в левой части правила вывода:
G[Z]={VT, VN, Z, P}
• VT – конечное множество терминальных символов
• VN – непересекающееся с VT конечное множество нетерминальных символов
• P – конечный набор порождающих правил вида (± ® І), где
• Z – начальный символ, Z VN
• V = VT VN — объединение словарей или общий словарь терминалов и нетерминаловПо иерархии грамматик Хомского выделяют 4 основные группы языков (и описывающих их грамматик). При этом наибольший интерес представляют регулярные и контексно-свободные (КС) грамматики и языки. Они используются при описании синтаксиса языков программирования. С помощью регулярных грамматик можно описать лексемы языка - идентификаторы, константы, служебные слова и прочие. На основе КС-грамматик строятся более крупные синтаксические конструкции - описания типов и переменных, арифметические и логические выражения, управляющие операторы, и, наконец, полностью вся программа на исходном языке.
Рассмотрим несколько примеров, иллюстрирующих введенные понятия:
а) Задана грамматика Г1. 0 и требуется определить язык, порождаемый этой грамматикой:
Г1. 0: Vт = {a, b, c}, Va = {<I>}, R = {<I> abc}.
Схема грамматики содержит одно правило, поэтому Г1. 0 порождает язык из одного слова
L(Г1. 0) = {abc}.
b) Задана грамматика Г1. 1 и требуется определить язык, порождаемый этой грамматикой .
Г1. 1 : Vт = {a, b, c}, Va = {<I>, <B>, <C>}
R = { <I> a<B>,
<B><C>d, <B>dc, <C> $}.
Построим все выводы в этой грамматике:
<I>a<B> a<C>dad, <I> a<B> adc.
Следовательно язык L(Г1. 1) = {adc, ad}.
В общем случае, если описано множество цепочек, представляющих собой некоторый язык, и требуется построить грамматику, порождающую это множество цепочек, то следует поступать так:
1) Выписать несколько примеров из заданного множества цепочек.
2) Проанализировать структуру цепочек, выделяя начало, конец, повторяющиеся символы или группы символов (т.е., определяя закономерности).
3) Ввести обозначения для сложных структур, состоящих из групп символов. Такие обозначения являются нетерминальными символами искомой грамматики.
4) Построить правила для каждой из выделенных структур, используя для задания повторяющихся структур рекурсивные правила.
5) Объединить все правила.
6) Проверить с помощью выводов возможность получения цепочек с разной структурой.
