Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #89, МАЙ 2006 г.

Пишем свой PHP

Бойко Артем (mr.prutik@mail.ru)

Хакер, номер #089, стр. 089-118-2


[пишем основу]

Теперь как ты, наверное, догадался, нам нужно считать все из этого файла (нашего исходника) для последующего анализа. Для этого воспользуемся классом ifstream, который стал доступен, когда ты подключил хидер fstream в самом начале нашего интерпретатора.

Сотри все содержимое функции main, кроме последней строки, и введи следующее:

ifstream fin;

// Создаем обьект fin класса ifstream.

fin.open(argv[1]);

// Читаем исходный код нашей программы

char buf[80];

// Создаем буфер для чтения из файла

while (fin.getline(buf, 80)) // читаем построчно файл

{

// Здесь будет происходить обработка

// исходного кода нашего скрипта

}

Наш интерпретатор будет построчно читать файл и как-нибудь его интерпретировать. Реализовать построчную интерпретацию куда проще, чем хитрые многопроходные системы. Давай теперь придумаем синтаксис нашего web-языка. Придумаем и тотчас реализуем.

Начнем, пожалуй, с комментариев, без которых никуда. Будем игнорировать всякую строку, начинающуюся символом #. Добавляем в главный цикл для этого соответствующую (кстати, всего одну) строку:

if (buf[0] == *"#" || strlen(buf) == 0) continue;

Смысл у нее простой: если первый символ считаемого буфера является символом # или размер буфера считываемой строки нулевой (то есть она пуста) тогда мы выполняем continue. Ключевое слово continue означает завершение текущего шага цикла и переход к следующему. Так-с, идем дальше.

Для удобной отладки скриптов я решил ввести в интерпретатор счетчик строк, указывающий на текущую читаемую строку. С его помощью, если вдруг в скрипте ошибка, можно всегда точно определить, где она находится. Реализует он все это дело элементарно. Объявляется переменная line перед циклом:

int line = 0;

И в самом начале цикла мы эту переменную увеличиваем на единицу:

++line;

Она нам еще пригодится.

Далее я решил, что все переменные в моем языке не будут иметь четкой типизации, то есть они не будут четко делиться на строковые, числовые и т.п. Для их хранения нам потребуется описать структуру. Я предлагаю вот такую:

struct my_type

{

char ch[30]; // имя переменной

char nm[255]; // значение переменной

};

Копия такой структуру хранит название одной переменной и ее значение. Чтобы была возможность хранить большее количество таких переменных, нужно описать массив подобного типа. Делается это так:

my_type vars[999]; // массив структур my_type

int vars_count = 0; // текущее количество переменных

Так мы и будем хранить все переменные. Все очень просто. Чтобы ты понял, к чему я стремлюсь, я заранее приведу пример скрипта для нашего web-языка. Надеюсь, синтаксис у тебя не вызовет вопросов.

#!/usr/bin/test

# адрес интерпретатора

pragma = first

# название программы

var

# описание всех переменных после слова var

# переменная = значение

test1 = 0

test2 = 0

# start сообщает нас о начале кода

start

# числовые операции

test1 = 9

test2 = test1

stop

# после слова stop код вообще не читается

Вот такого плана будут все описанные на нашем языке программы. Для того чтобы это реализовать, нам потребуются дополнительные, не очень сложные функции. Их прототипы приведены ниже, а полный их код ты найдешт на диске.

Назад на стр. 089-118-1  Содержание  Вперед на стр. 089-118-3