Компилятор Делавар. Описание 16-битной версии компилятора Делавар
Предлагаю вашему вниманию любительский, пока только 16-разрядный консольный компилятор, позволяющий создавать исполняемые файлы в самом простом бинарном формате. Используемая платформа Win32, однако компилятор можно собрать под MS DOS и Линукс. Так как компилятор "Делавар" фактически транслирует исходный код в мнемокод х86 ассемблера, то для создания приложений для Линукс потребуется переделка выходного формата, например, для NASM'а. Сейчас используется ассемблер моего же "производства".
Одним из главных отличий этого компилятора от других компиляторов, является то, что можно писать программы на разных языках. Имеется в виду возможность использования национальных ключевых слов и имен переменных. Программы на данный момент можно писать на русском и английском языках. Язык программирования является процедурным. В планах есть идея добавить объектно-ориентированные возможности, сделать возможность компиляции 32-битного кода и т.д. Идей как улучшить компилятор достаточно, была бы возможность... Синтаксис языка во многом позаимствован из языка С, отчасти - из Паскаля.
Содержание
Доступны следующие типы данных:
char (знак) - однобайтовый символ byte (байт)- беззнаковое 8-разрядное целое bool (логика) - однобайтовая логическая переменная int (целое) - знаковое 16-разрядное целое word (слово) - беззнаковое 16-разрядное целое string (строка) - строка однобайтовых символов.
Поддерживаются составные типы (структуры и объединения). Объявление структуры начинается с ключевого слова type (тип). Например: type { int x, y } z. Соответственно обращение к полю структуры осуществляется через точку: z.x. Реализована инициализация структур. Например, z A = {5, 10}. Аналогично объявляются объединения (в русской версии "союз", в английской - union) - union {byte z; int x; } y. Поддерживаются также многомерные массивы и их инициализация. Например, int x[2, 3] = { {0, 0, 0}, {0, 0, 0} }. Реализована блочная область видимости переменных. Блок представляет из себя список инструкций и выражений, заключенных в фигурные скобки.
Функции
Объявление и тело функции начинается с ключевого слова function (функция). Главная функция (точка входа в программу) называется Start (Старт). Передача параметров в пользовательскую функцию и возвращаемое ею значение пока возможны только для простых типов. Синтаксис прототипа функции выглядит следующим образом:
function [stype] namef ([stype name_par1, ..., stype name_parN]) declaration,
где stype - объявление возвращаемого функцией значения (например, int); namef - имя функции; name_par - имя параметра; [] - в квадратные скобки заключены необязательные элементы. Объявление прототипа функции должно завершаться ключевым словом declaration (обьявление) или просто точкой с запятой ";". Естественно, прототипы функций можно не указывать, но в этом случае, необходимо описание функции до ее вызова.
Синтаксис тела функции выглядит так:
function [stype] namef ([stype name_par1, ..., stype name_parN]) Block,
где Block - последовательность операторов, заключенных в фигурные скобки;
Встроенная функция одна: print (печать), которая может иметь два параметра. Использование: print([spec,] par), где spec - спецификатор, par - параметр. Спецификатор должен быть заключен в апострофы, он необязателен. 'd' ('ц') - указывает вывести значение в числовом формате, 'c' ('з') - в символьном формате, 'u' ('б') - беззнаковом числовом формате, 's' ('с') - в строковом формате. В качестве параметра par функция print может принимать переменную любого простого типа или выражение, а также непосредственное значение.
Простым переменным возможно присваивать непосредственные значения или выражение. Например, int x = 5; char ch = 'A'; byte y = 15 - x; bool b = true; (в русской версии - "истина", а также можно присвоить значение false ("ложь" в русс. версии)), string s = "This is string".
Каждую инструкцию возможно завершать точкой с запятой ";", хотя это не обязательно и даже не предусматривалось, кроме случаев использования в инструкции for и объявления функции. Подробнее смотрите в тестовых примерах.
Приведу пример простейшей программы:
function Start() { print("Hello, World!") }
Имеется три инструкции (пока, цикл, если-иначе): 1) while(cond) Block, 2) for([stype] [[var = ]expr]; [cond]; [expr]) Block, 3) if(cond) Block [else Block],
где cond - логическое выражение; expr - арифметическое выражение; stype - объявление простого типа (например, int); var - имя переменной; Block - последовательность операторов, заключенных в фигурные скобки или просто одиночная инструкция; [] - в квадратные скобки заключены необязательные элементы.
Реализованы также операторы break (прервать), continue (продолжать), return (вернуть). Последний оператор может иметь в качестве параметра возвращаемое выражение. Есть особенность в реализации инструкции for. Область действия объявляемой новой переменной, например: for(int i = 0; i < 10; i++);, не выходит за область действия оператора for.
Также имеется возможность делать ассемблерные вставки с помощью ключевого слова assembler (ассемблер). Блок инструкций на ассемблере должен быть заключен в фигурные скобки.
Для числовых данных реализованы бинарные операции сложения, вычитания, умножения, деления, остаток от деления (+, -, *, /, %), унарные операции минус (-), декремент (--), инкремент (++), а также операции +=, -=, *=, /=. Для числовых, булевых переменных реализованы также логические операции "И"(&&) и "ИЛИ"(||), "НЕ"(!) и операции сравнения >, <, >=, <=, ==, !=. Тип данных string является фактически указателем на строку символов. Для этого типа данных, а также числового и логического типов, допустима операция присваивания (=). Реализация типа "указатель" начата, но не закончена.
Возможны однострочные и многострочные комментарии, аналогично используемым в языке С. Причем многострочные комментарии могут быть вложенными.
Структура программы
Общая структура программы следующая:
[объявления прототипов функций]
[объявления глобальных переменных и структур]
текст тел функций
Пример более сложной программы:
/****************************************************** Функция поэлементного сложения двух прямоугольных матриц
- /
int v1[3, 2], v2[3, 2] int c[3, 2]
function MatrixPlusMatrix (int n, int m)
{
for (int i = 0; i < n; i++) for (int j=0; j < m; j++) c[i, j] = v1[i, j] + v2[i, j]
}
function Start()
{
int n = 3, m = 2
for (int i = 0; i < n; i++) for (int j=0; j < m; j++) { v1[i, j] = 1 v2[i, j] = 2 }
MatrixPlusMatrix(n, m)
for(int i = 0; i < n; i++) for (int j=0; j < m; j++) print(c[i, j]) }
Русские ключевые слова
Набор ключевых слов, сообщений и спецсимволов должны находиться в текстовом файле dc.res. Как пример, в файле dc_en.res хранятся англоязычные ресурсы компилятора, русские - в файле dc_ru.res.
Для переключения с одного языка на другой достаточно поменять содержимое файла dc.res. Формат строк файла dc.res очень прост: строка символов должна завершаться символами перевода строки (и возврата каретки). Первые две строки в файле dc.res содержат национальный алфавит. Третья строка - спецсимволы для инструкции print. Далее следуют служебные сообщения, набор ключевых слов и сообщения об ошибках. Примеры программ хранятся в папке "EX". Для создания исполняемого файла достаточно поместить в файл test.d исходный текст и запустить пакетный файл test.bat. Про более удобный способ компиляции примеров читайте здесь. Смотрите, там вроде все понятно.
P.S. Компилятор Делавар не завершен... Поэтому есть, к сожалению, необработанные исключения и ошибки. Буду рад вашим замечаниям и предложениям. Пишите в гостевую книгу. Для удобства работы используйте менеджер файлов FAR.
См. также
Яндекс | Картинки | Видео | Карты | Карты ОСМ | Спутник | Гугл | Вольфрам-Альфа | РуВики | EnWiki