- •1. Постановка задачи
- •Исходные данные:
- •Описание синтаксиса входного языка:
- •Описание семантики входного языка:
- •Объявления и области действия
- •Операции.
- •Лексический анализ
- •Определение синтаксиса лексем
- •49 Таблица констант
- •Тестирование лексического анализатора
- •Описание кс-грамматики входного языка
- •Разбиение на подграмматики
- •Описание языка триад
- •Построение атрибутной транслирующей грамматики
- •Построение атрибутного дмп – процессора
- •Организация взаимодействия дмп-процессоров
Описание семантики входного языка:
Программа представляет собой множество пользовательских типов данных (далее - классов), находящихся в одном каталоге и связанных включением (import), один из которых обязательно имеет функцию-член с сигнатуройvoid main(). В каждом файле может быть описан только один класс. Класс имеет поля, которые могут быть членами-данными встроенных или же определяемых пользователем типов (разработанных классов) или членами-функциями (далее - просто функциями). Инициализация члена-данного может быть осуществлена во время объявления этого члена-данного. Поля класса должны иметь уникальные имена. Переменные, объявленные внутри одно блока должны иметь уникальные имена. Областью видимости локальной переменной является блок. Локальные переменные объявленные внутри блока перекрывают переменные с теми же именами, объявленными вне этого блока. Имя формально параметра функции также перекрывает имя переменной, объявленной как член-данное класса. Время жизни неименованных переменных (используемых в выражениях) ограничивается временем вычисления результата выражения. Время жизни локальной переменной ограничивается блоком, в котором она была определена.
Существует набор зарезервированных языком слов. Их нельзя использовать для названия <идентификатора>.
Зарезервированные слова:
While |
Class |
If |
Package |
Else |
String |
Goto |
Void |
Int
|
Char |
Double |
Import |
Базовые типы данных языка
Тип |
Размер, байт |
Диапазон значений |
int |
4 signed |
−2,147,483,648 to +2,147,483,647 |
float |
4 signed |
. |
char |
2 unsigned |
0 to 65,535 |
String |
ограничено размером ОП |
. |
String-переменной может быть назначена строковая константа (строка символов в двойных кавычках);
Язык - регистрозависимый
Объявления и области действия
Каждая переменная, встречающаяся в программе, должна быть объявлена до места первого её использования.
Область действияпеременной начинается после точки её объявления и заканчивается, тогда когда заканчивается блок, в котором находится объявление.
Нельзя создавать переменные с одинаковыми именами и пересекающимися областями действия.
Операции.
Операции одного приоритета выполняются слева направо.
Арифметические операции.
Используются в выражениях, стоящих в правой части присваивания.
Знак операции |
Название операции |
Порядок выполнения |
++ |
Увеличение на единицу |
Справа налево |
-- |
Уменьшение на единицу |
Справа налево |
* |
Умножение |
Слева направо |
/ |
Деление |
Слева направо |
+ |
Сложение |
Слева направо |
- |
Вычитание |
Слева направо |
Операции ++ и -- применимы только для типа int.
Операции отношения.
Используются при вычислении условных выражений.
Знак операции |
Название операции |
Порядок выполнения |
< |
Меньше |
Слева направо |
<= |
Меньше или равно |
Слева направо |
> |
Больше |
Слева направо |
>= |
Больше или равно |
Слева направо |
== |
Равно |
Слева направо |
!= |
Не равно |
Слева направо |
Операции отношения применимы только к типам int,float иchar. В случае сравнения переменных (или результатов выражений) разного типа, - типы преобразуются согласно правилам преобразования типов. Строки сравниваются посредством зарезервированной ф-ии.
В арифметическом выражении приоритет операций обычный. Деление на ноль запрещено.
Правила преобразования типов:
Операции |
Тип левого (правого) операнда |
Тип правого (левого) операнда |
Результирующий тип |
+, -, *, /, <=, <, >=, >, ==, != |
int |
float |
float |
+ |
int |
string |
string |
+ |
char |
string |
string |
Все назначения, явные или через передачу параметров в вызовах методов, проверяются на совместимость типов;
Если какой-либо из операндов имеет тип double, другой операнд тоже преобразуется к double.
Если один из операндов типа int, а другой – типаchar, то он приводится к типуint;
Если один из операндов типа String, а другой – числового типа либоchar, то первый приводится ко второму типу (эквивалентно операции вычисления длины строки)
Если один из операндов имеет структурированный тип, то при выполнении арифметических операций он приводится к типу int, при чём значение типа int соответствует длине строкиОперации ++ и – применимы только для типа int.
В операции условного присваивания значение после знака ? и значение после символа : должны быть одного типа и приведены к типу переменной, которой присваиваются.
Последовательность операторов, разделенных точкой с запятой, означает поочередное выполнение действий.
Комментарии
1) многострочным комментарием считается текст, заключенный в символы ‘/*’и ‘*/’, может находиться в любом месте программы, если он не разрывает лексемы.
2) однострочным комментарием считается текст, находящийся после символов ‘//’.
Оператор присваивания
Синтаксис:
<Assignment>::=<ExpressionL> = <ExpressionR>;
<ExpressionL>::=<Identifier>{.<Identifier>}
Порядок выполнения операции присвоения:
Вычисляется значение выражения в правой части, затем оно присваивается переменной в левой части, если тип значения и переменной совпадают. В противном случае присваивание не выполняется и пользователю выдается сообщение об ошибке.
Условный оператор
Синтаксис:
If (<ParExpression>) <Block> [ else <Block>]
Вначале вычисляется значение логического выражения <ParExpression>. Если оно возвращает 1 – истина, то выполняется первый блок операторов <Block>, иначе выполняется блок операторов <Block>, стоящий после ключевого словаelse,если оно присутствует.
Оператор условного присваивания
Синтаксис:
<CondAssignment>::= (<ParExpression>)? <ExpressionR>: <ExpressionR>;
Вычисляется значение логического выражения <ParExpression>, если значение = 1(истина), то вычисляется значение выражения <ExpressionR>, стоящего после “?” и до “:” и присваивается переменной в левой части, иначе вычисляется значение выражения <ExpressionR>, стоящего после “:” и оно присваивается переменной. Причем присваивание выполняется, если тип вычисленного значения и переменной, стоящей в левой части совпадают. В противном случае присваивание не выполняется и пользователю выдается сообщение об ошибке.
Оператор цикла
Синтаксис:
while (<ParExpression>) <Block>
Вычисляется значение логического выражения <ParExpression>, если оно = 1 (истина), то тогда выполняется тело цикла – блок операторов <Block>, после выполения последнего оператора этого блока, опять вычисляется значение выражения <ParExpression>, и если оно = 1, то выполняется <Block> и так до тех пор, пока значение <ParExpression> не станет равным 0 (ложь). Предполагается, что тело цикла <Block> изменяет переменные, которые используются в <ParExpression>, таким образом изменяя значения этого выражения после каждого выполнения тела цикла, иначе может случиться зацикливание.
Классы
Пользователь может создавать свои собственные типы данных, объявляя классы.
Класс объявляется следующим образом
<ClassDeclaration>::=class<Identifier><ClassBody>
<ClassBody>::={{<ClassBodyDeclarations>}}
<ClassBodyDeclaration>::=<FieldDeclaration> | <MethodDeclaration>
За ключевым словом classследует идентификатор – имя класса, оно должно быть уникально в пределах программы и не должно совпадать с именами переменных и меток.
Тело класса состоит из определения методов и полей. Поле – это объявление (плюс может быть инициализация) переменной, атрибута класса. Метод – определение функции класса.
Имя класса может быть использовано пользователем при создании объектов этого класса, например
newMyClass();
Функции
В качестве типа возвращаемого значения функция может выступать любой тип данных – встроенный или определенный пользователем. Если в качестве возвращаемого значения указано ключевое слово void, это значит, что функция ничего не возвращает, в таком случае вызов этой функции не может стоять в правой части выражения, т.е. бытьr-value.
Если функция имеет возвращаемое значение, то в реализации такой функции должен присутствовать оператор
return <ExpressionR>;
причем, значение, получаемое при вычислении <ExpressionR>, должно совпадать с типом возвращаемого значения функции.
Если в качестве возвращаемого значения указано ключевое слово void, то ключевое словоreturn;может как присутствовать, так и отсутствовать в теле функции. Причем в таком случае послеreturnдолжно стоять “;”, так как в таком случае функция ничего не возвращает.
Ключевое слово return определяет точку выхода из функции, рассчитывается значение выражения, стоящее послеreturn (если оно есть), это происходит возврат в то место программы, откуда эта функция вызывалась, причем вычисленное значение возвращается как результат выполнения функции (или ничего не возвращается).
Операции над строками
1) Конкатенация двух строк
concat(<ExpressionR>,<ExpressionR>)
Конкатенация двух строк, результат – строка.
str1 = <ExpressionR>, ее длина l1
str2 = <ExpressionR>, ее длина l2
Вычисляются значения параметров, они должны быть типа string, иначе пользователю выдается сообщение об ошибке.
str3 =str1 +str2, ее длинаl3 =l1 +l2
Результирующая строка получается конкатенацией двух строк, которые переданы в качестве параметров (создается новая переменная типа String, в нее записывается значение первой строки и приписывается вторая строка); длина результирующей строки равна сумме длин строкstr1 иstr2. Тип возвращаемого значения функции – строка.
Пример: concat(“123”, “abc”) возвращает строку “132abc”.
2) Замена подстроки в строке
replace(<ExpressionR>, <ExpressionR>, <ExpressionR>)
Первый параметр функции – входная строка sourceStr, второй параметр – строка, которую надо заменитьstrOld, третий параметр – строка, на которую надо заменитьstrNew.
Вычисляются значения параметров, они должны быть типа string, иначе пользователю выдается сообщение об ошибке.
В строке происходит sourceStrпроисходит поиск всех вхождений подстрокиstrOld, каждое вхождение этой подстроки заменяется на строку strNew. Причем изменяется значение исходной строки, т.е. новая переменная не создается. Тип возвращаемого значения функции – строка.
Пример: replace (“123qw45qwe”, “qw”, “m”) возвращает строку “123m45me”.
3) Поиск подстроки в строке
find(<ExpressionR>, <ExpressionR>)
Первый параметр функции – входная строка sourceStr, второй параметр – строка, которую нужно найтиstrToFind.
Вычисляются значения параметров, они должны быть типа string, иначе пользователю выдается сообщение об ошибке.
В строке sourceStrищется первое вхождение подстрокиstrToFind, если такое вхождение есть, то тогда функция возвращает номер символа, с которого начинается это вхождение. Если строка не найдена, то возвращается -1. Тип возвращаемого значения функции – целое числоint.
Пример: find(“teststr”, “st”) возвращает2.
4) Вычисление длины строки
length(<ExpressionR>)
Параметр функции – входная строка sourceStr, длину которой надо определить.
Вычисляется значение параметра, он должен быть типа string, иначе пользователю выдается сообщение об ошибке.
Происходит подсчет количества символов в строке sourceStr. Это число возвращается в качестве результата. Длина пустой строки равна нулю. Тип возвращаемого значения функции – целое числоint.
Пример: length(“teststr”) возвращает 7.
5) Доступ к подстроке в заданной строке
substring(<ExpressionR>, <DigitSequence>, <DigitSequence>)
Первый параметр функции – входная строка sourceStr, второй параметр – номер символа во входной строке, начало подстрокиstart, третий параметр – номер символа во входной строке, конец подстрокиend.
Вычисляется значение первого параметра, он должен быть типа string, иначе пользователю выдается сообщение об ошибке.
Вычисляются значения второго и третьего параметров, они должны быть типа int, иначе пользователю выдается сообщение об ошибке.
Пусть длина входной строки sourceStrравнаlength, тогда должно выполняться условие
0<=start<end<length
если оно не выполняется, то пользователю выдается сообщение об ошибке.
Функция возвращает подстроку, которая начинается с символа с номером startво входной строке и заканчивается символом с номеромend, при этому создается новый объект типаstring.
Тип возвращаемого значения функции – строка.
Пример: subsring(“teststr”, 1, 4) возвращает “est”.