====== Эмулятор Эль76-Эльбрус (версия 1.0b) ======
//Copyright © ВК№2 Сергей Стрелков, Александр Страшнов, Александр Ковернинский, Алексей Бояршинов//
(Ссылки:
{{http://web.archive.org/web/20030710092032/www.mstu.ru/studies/Others/War/IlbrusLanguage-emul.rar}},
{{http://web.archive.org/web/20030710091904/www.mstu.ru/studies/Others/War/IlbrusLanguage-docs.rar}})
Эмулятор L76 предназначен для создания и выполнения программ на языке Эль76 Эльбрус под управление операционной системы Windows 95/NT.
Эмулятор включается в себя компилятор, поддерживающий некоторое подмножество языка Эль76 (смотри раздел [[#Алфавит]]), виртуальную машину Эль76, отладчик программ и редактор с подсветкой синтаксиса.
===== Алфавит =====
Конструкции языка представляются с помощью набора базовых символов. В этот набор входят:
* русские и латинские буквы верхнего регистра
* цифры от 0 до 9
* специальные символы [ . < ( + @ ] $ * ) & ; : ' # / | > , % ! "- = _ ^
* пробел.
В эмуляторе применяется кодировка Windows 1251.
===== Лексемы =====
Лексический элемент языка - это <[[#Идентификатор|идентификатор]]>, <[[#Число|число]]>, <[[#Поэлементное представление|поэлементное представление]]>, подчеркнутый идентификатор или [[#Разделители|разделитель]]. Лексические элементы строятся из <букв>, <цифр>, <двоичных цифр>, <восьмеричных цифр>, <шестнадцатеричных цифр> и <литер>.
> <буква> ::== А | В | С | D | Е | F | G | Н | I | J | К | L | M | N | O | P | R | S | T | U | V | W | X | Q | Y | Z | Ю | Б | Ц | Д | Ф | Г | Й | Л | Я | Ч | Ж | Ы | З | Ш | Щ | Э | Ъ | У
> <цифра> ::== 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
> <двоичная цифра> ::== 0 | 1
> <восьмеричная цифра> ::== 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
> <шестнадцатеричная цифра> ::== 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | А | В | С | D | Е | F
> <литера>::== <буква> | <цифра> | <вертикальная черта> | <кавычка> | [ | . | < | ( | + | @ | ^ | ] | $ | * | ) | ; | : | ‘ | # | / | , | % | > | ! | _ | & | = | - | <пробел>
===== Идентификатор =====
Идентификаторы используются для обозначения переменных и констант, вводимых с помощью описаний.
> <идентификатор> ::== <[[#Буква|буква]]> {<буква или цифра>} ...
> <буква или цифра> ::== <[[#Буква|буква]]> | <[[#Цифра|цифра]]>
===== Число =====
Числа <Целое> и <вещественное> - это десятичные числа в их обычном понимании. <Порядок> представляет собой степень числа 10.
> <целое> ::== <цифра>...
> <вещественное> ::== <целое>.<целое>{<порядок>} | <целое><порядок>
> <порядок> ::== е{<знак>}<целое>
> <знак> ::== + | -
===== Поэлементное представление =====
Поэлементное представление используется для обозначения строк, наборов и для обозначения чисел во внутреннем представлении.
> <поэлементное представление> ::== 1"<двоичная цифра>..." | 3"<восьмеричная цифра>..." | 4"<шестнадцатеричная цифра>..." | 8"<литера>..."
<Поэлементное представление> задает смежную последовательность двоичных, восьмеричных, шестнадцатеричных и байтовых элементов. Цифра, предшествующая первой кавычке определяет размер элемента в разрядах и способ кодировки. Длина последовательности (в разрядах) равна произведению размера элемента на количество элементов.
===== Формат =====
> <формат> ::== <простой формат> | <строчный формат>
> <простой формат> ::== **ф32** | **ф64** | **ф128**
> <строчный формат> ::== **ф1** | **ф4** | **ф8**
В данной версии поддерживается только **ф32** формат.
===== Разделители =====
Разделители - это специальные символы и следующие слитные сочетания:
:= <:= <= > ** :=: +: -: /: *: ^: >= <= <> >/ >=/ <=/ =/ <>/ // && % *
===== Комментарии =====
Комментарий может быть коротким и длинным. Короткий комментарий начинается с символом % и заканчивается концом той строки, на которой он начался. Непосредственно за символом % не может следовать символ *. Длинный комментарий - это последовательность символов, которая начинается и заканчивается ограничителем длинного комментария. Таким ограничителем является пара символов %*. Длинный комментарий может занимать несколько строк.
===== Описание =====
<Описание> вводит переменную или константу и связывает с ней идентификатор. Диапазон текста программы, внутри которого эта связь существует, называется областью действия описания.
В программе может быть несколько описаний с одним и тем же идентификатором. 3а счет текстуальной вложенности конструкций области действия подобных описаний могут перекрываться. Тогда идентификатор в данной точке текста программы понимается в том смысле, который ему придан в минимальной охватывающей эту точку области действия.
Контекстом идентификаторов для данной точки текста программы называется множество идентификаторов, описание которых действует в этой точке.
С помощью <описаний> вводятся простые переменные и следующие константы: простые константы, статические ситуации, пропедуры-константы, базы участков базированных областей памяти, метки предложений, описатели полей и текстовые макросы.
<Описание> может встречаться в составе последовательности описаний в начале <закрытого предложения> или <последовательного предложения>. Кроме того, существуют специфические описания, являющиеся составной частью связанных с ними конструкций. К ним относятся описание формальных в заголовков процедуры, описания статических ситуаций в заголовке структурного предложения и описание параметра цикла в заголовке цикла. Область действия описаний указывается в последующих разделах при изложении семантики этих конструкций. Общие для всех случаев ограничения состоят в следующем:
* внутри одной и той же цепочки описаний один и тот же идентификатор не может быть описан дважды;
* описание идентификатора должно предшествовать его использованию.
> <описание> ::==
> <описание простых переменных> |
> <описание простых констант> |
> <[[#Описание процедур|описание процедур-констант]]> |
> <[[#Метки|описание меток]]>
===== Простые константы =====
<Описание простых констант> вводит константу, значением которой является значение <выражения>, находящегося в правой части <идентификации константы>. Одно описание может вводить несколько констант.
> <описание простых констант> ::== **конст** <список идентификации констант>
> <идентификация константы> ::== <идентификатор> = <выражение>
Если в правой части <идентификация константы> находится выражение статического класса, то вновь созданная константа является константой статического класса.
В правой части <идентификации константы> нельзя рекурcивно использовать <идентификатор> левой части.
===== Простые переменные =====
<Описание простых переменных> вводит одну или несколько переменных одинакового <простого формата> и связывает с ними <[[#Идентификатор|идентификаторы]]>.
> <описание простых переменных> ::== <простой формат><список идентификации переменных>
> <идентификация переменной> ::== <[[#Идентификатор|идентификатор]]> {:= <выражение>}
> <[[#Идентификатор|идентификатор]]> = <[[#Идентификатор|идентификатор]]>
<Идентификация переменной> может содержать <выражение>, значение которого задаёт начальное значение переменной. В этом <выражении> нельзя использовать <идентификатор> из левой части <идентификации переменной>.
(По умолчанию переменная формата **ф32** или **ф64** инициализируется пустым объектом соответствующего формата, а переменная формата **ф128** - пустым объектом формата **ф64**).
В области действия описания переменная обозначается <[[#Идентификатор|идентификатором]]>, связанным с нею при описании.
===== Массив =====
Массив создается с помощью <генератора массива>. <Генератор в маcсива> предназначен для создания многомерного в-массим, а <генератор с-вектора>-для создания с-веитора.
> <генератор массива> ::== <генератор в-массива> | <генератор с-вектора>
> <генератор в-массива> ::== <локализация>[<список выражений>]<формат>
> <генератор с-вектора> ::== <локализация> **вект** [<выражение> {: <выражение>}] <формат>
> <локализация> ::== **лок** | **глоб**
В-массив состоит из элементов заданного <формата>. Размерность массива равна числу <выражений> в скобках. Индекс по р-му измерению может заключаться в пределах от 0 до Kр-1, где Kр - значение р-го <выражения> (Kр - целое неотрицательное число).
Значением генератора является указатель паспорта созданного массива. Например, в результате выполнения генератора
|| **лок** [10,10] **ф64** ||
создается матрица размером 10x10 элементов формата **ф64**. Если генератор массива использовать в правой части описания константы, например
|| **конст** с = лок [10,10] **ф64**; ||
то образуется описание, эквивалентное традиционному описанию массива.
С-вектор состоит из к элементов заданного формата, где к - значение первого <выражения>. Значением генератора является указатель, описывающий созданный вектор.
Локализация. Компонента <локализация> определяет время жизни созданного массива: **лок** означает, что массив является локальным, а **глоб**-глобальным.
===== Замкнутое предложение =====
<Замкнутое предложение> представляет собой простейший способ структурирования описаний и предложений. Оно используется в основном для организации блоков с локальными описаниями (в частности для оформления тела процедуры), а также для изменения порядка вычислений в <формулах>. <Замкнутое предложение> представляет собой <последовательное предложение>, заключенное в скобках: ( и ), или **начало** и **конец**.
> <замкнутое предложение> ::== (<последовательное предложение>) | **начало** <последовательное предложение> **конец**
Пример. Блок с описанием.
начало ф128 с := вещ128 0;
для i до вг цикл
c := c + в128 f(i)**2;
повторить
конец
===== Условное предложение =====
Условное предложение позволяет из нескольких альтернатив выбрать и выполнить ту, для которой <условие> принимает значение истина.
> <условное предложение> ::== **если** <выражение> **то** <последовательный оператор>
> {**инес** <выражение> **то** <последовательный оператор>}...
> {**иначе** <последовательный оператор>}
> **все**
При выполнении <условного предложения> последовательно выполняются <условия> до первого, <выражение> которого принимает значение **истина**. Затем выполняется соответствующее <последовательное предложение>. Если такого <условия> не нашлось, по <условное предложение> содержит альтернативу **иначе**, то выполняется <последовательное предложение> из этой альтернативы. Если же ни одно <условие> не выполнилось и нет альтернативы **иначе**, то ни одно <последовательное предложение> не выполняется. <Условное выражение> и <условная переменная> с необходимостью должны содержать альтернативу **иначе**.
===== Выбирающее предложение =====
<Выбирающее предложение> позволяет выбрать одну из пронумерованных альтернатив и выполнять ее. Номер выполняемой альтернативы вычисляется в заголовке <выбирающего предложения>.
> <выбирающий оператор> ::== **выбор** <выражение> **из**
> {{<выражение>:,}... <выражение>: <последовательный оператор>,}...
> {<выражение>:,}... <выражение>: <последовательный оператор>
> **иначе** <последовательный оператор>
> **всевыб**
Альтернативы <выбирающего предложения> нумеруются либо в явной форме, либо неявно. В первом случае <выбирающее предложение> строятся из <размеченных альтернативных предложений>. Каждой альтернативе можно приписать один или несколько <номеров>. <Номер>–это выражение статического класса, значением которого может быть целое или набор.
Во втором случае номер в явном виде отсутствует, и считается, что альтернативы пронумерованы от 0 до n–1, где n– число альтернатив.
Выполнение <выбирающего предложения> происходит следующим образом. Выполняется <вычисление номера>. Значение <выражения> определяет номер альтернативы, которую следует выполнить. Если такая альтернатива существует, то выполняется ее <последовательное предложение>. Если же такой альтернативы нет, но есть альтернатива **иначе**, то выполняется последовательное предложение из альтернативы иначе. В противном случае ни одно <последовательное предложение> не выполняется. <Выбирающее выражение> и <выбирающее переменную> обязательно должны содержать альтернативу **иначе**.
Примеры.
выбор день из
1:, 3:, 7: печать(стр8”дневная смена”)
2:, 4: печать(стр8”вечерняя смена”)
5:, 6: печать(стр8”выходной день”)
иначе печать(стр8”неверно задан день”)
всевыб
===== Цикл =====
Конструкция <цикл> предназначена для организации повторяющегося процесса выполнения ее <операторов>.
> <цикл> ::== {**для** <идентификатор> {**от** <выражение>} {**до** <выражение> | **вниздо** <выражение>}} **цикл** <последовательный оператор>
> **повторить**
Повторяющееся выполнение <операторов> цикла без заголовка может быть прекращено с помощью <структурного перехода>, пересекающего границы цикла (и, кроме того. с помощью обычного перехода на метку).
Цикл с заголовком определяет, что <операторы> выполняются столько раз. сколько задано в <заголовке цикла>.
> <заголовок цикла>::== **для** <идентификатор> {**от** <выражение>} {<компонента-до>}
> | **от** <выражение> {<компонента-до>}
><компонента до> ::== **до** <выражение> | **вниздо** <выражение>
В <заголовке цикла> задается <идентификатор> параметра цикла. Появление этого идентификатора в заголовке одновременно является и его описанием в пределах данного <цикла>. Начальное значение параметра цикла задается <выражением> в компоненте **от**, а конечное значение -- выражением в <компоненте-до>. Ограничитель <компоненты-до> задает направление изменения параметра цикла: на каждой итерации его значение увеличивается на 1 в случае ограничителя **до** и уменьшается на 1 в случае ограничителя **вниздо**.
Семантика выполнения цикла с заголовком отображается следующей программой:
... установить начальное значение i...
до кц цикл
если (i–u)*s > 0 то кц! все;
... выполнить операторы цикла ...
... увеличить (уменьшить) i на 1 ...
повторить
где i – параметр цикла (начальное значение задается в заголовке), u–конечное значение параметра цикла, s = 1 для цикла по возрастанию значения параметра и s=–1 для цикла по убыванию значения параметра.
Начальное и конечное значение параметра цикла вычисляется один раз при входе в цикл. Значения <выражений> должны быть целыми числами. В. <выражениях> <заголовка цикла> нельзя использовать <идентификатор> параметра того же цикла. Если компонента **от** и/или <компонента-до> опущены, то начальное и/или конечное значение выбираются по умолчанию. Умолчание для .начального значения –0, а для конечного значения –220–1.
Параметр цикла на каждой итерации рассматривается как константа. Его значение нельзя изменять с помощью присваивания. его нельзя использовать в качестве параметра, передаваемого именем, и в качестве объекта при формировании указателя.
Идентификатор параметра цикла действует только внутри цикла. Однако, если выполнение цикла прекращается <структурным переходом>, то текущее значение параметра можно передать в качестве фактического параметра реакции.
Пример. Найти значение x в векторе а[0;n+1]
начало
а[n] :-= x;
ix := до найден
для i до n цикл
если а[i] = x то найден!(i) все
повторить
при найден(k):
если k = n то -1! иначе k все
всесит
конец
Компоненту для можно опускать в том случае, если в <операторах> цикла параметр цикла не используется.
<Описания> из тела <цикла> выполняются один раз при входе в цикл. Областью действия каждого такого описания является вся последующая часть <цикла>, вплоть до закрывающего ограничителя поморить.
Пример. Умножение матриц а и b размера nxn.
для i до n-1 цикл
ф128 cij;
для j до n-1 цикл
cij := 0;
для k до n-1 цикл
сij := сij + а [i,k] умнд b[k,j]
повторить
с[i,j]:= вещб4окр сij % округление результата
повторить
повторить
===== Структурное предложение =====
> <структурный оператор> ::== **до **<[[#Идентификатор|идентификатор]]> {,<идентификатор>} <закрытое предложение>
===== Описание процедур =====
> <описание процедур-констант> ::== **процедура** <идентификатор> { = <текст процедуры>} {,
> <идентификатор> { = <текст процедуры>}}...
> <текст процедуры> ::== **проц** ({**ф32** | **ф64** | **ф128**** **<идентификатор>{,<идентификатор>}...;} **ф32** | **ф64**
> | **ф128**** **<идентификатор>{,<идентификатор>}...) <закрытый оператор> | **функция** ({**ф32** | **ф64** | **ф128**** **<идентификатор>{,<идентификатор>}...;} **ф32** | **ф64** | **ф128**** **<идентификатор>{,<идентификатор>}...) <закрытое выражение>
===== Метки =====
> <описание меток> ::== **метка** <идентификатор> {, <идентификатор>}...
===== Переход =====
> <переход> ::== **на **<идентификатор>
===== Ситуации =====
> <описание статических ситуаций> ::== **статсит** <идентификатор> {, <идентификатор>}...
===== Преобразование типов =====
В данной версии поддерживаются следующие операции преобразования типов:
* **целокр** - в целое с округлением
* **целобр** - в целое с обрубанием
* **вещокр** - в вещественное с округлением
* **вещобр** - в вещественное с обрубанием
===== Генерация случайных чисел =====
Функция //случ()// возвращает случайные числа равномерно распределенные в интервале от 0 до 1 числа.
Пример.
ф32 ы := случ();
===== Вывод в окно терминала =====
Для вывода информации в окно терминала используются три встроенные функции.
Функция //печать(...)// осуществляет вывод числа.
//Пример.//
ф32 ы;
ы := 12345;
печать(ы)
Функция //печатьмс(...)// осуществляет вывод массива символов.
//Пример.//
ф32 ы;
ы := стр8 8"абракадабра";
печатьмс(ы)
Функция печатькс() переводит курсор терминала на новую сроку.
===== Ввод из окна терминала =====
Для ввода информации из окна терминала используются две встроенные функции.
Функция //ввод()// осуществляет ввод с клавиатуры числа.
//Пример.//
ф32 ы;
ы := ввод();
печать(ы)
Функция //вводмс()// осуществляет ввод с клавиатуры массива символов.
//Пример.//
ф32 ы;
ы := вводмс();
печатьмс(ы)
===== Математические функции =====
В данной версии поддерживаются следующие встроенные математические функции:
* //синус//(**ф32** x) — синус х
* //косинус//(**ф32** x) — косинус х
* //тангенс//(**ф32** x) — тангенс х
* //котангенс//(**ф32** x) — котангенс х
* //арксинус//(**ф32** x) — арксинус х
* //арккосинус//(**ф32** x) — арккосинус х
* //арктангенс//(**ф32** x) — арктангенс х
* //арккотангенс//(**ф32** x) — арккотангенс х
* //арктангенс2//(**ф32** x) — арккотангенс2 х
Аргумент тригонометрических функций задается в радианах.
* //логарифм//(**ф32** x) — натуральный логарифм х
* //экспонента//(**ф32** x) — е в степени х