Дипломы, курсовые, рефераты, контрольные...
Срочная помощь в учёбе

Создание программы-интерпретатора для обработки исходных текстов программ, выполняющих действия над комплексными числами

КурсоваяПомощь в написанииУзнать стоимостьмоей работы

В настоящее время языки высокого уровня стали основным средством разработки программ. Поэтому компиляторы составляют существенную часть системного программного обеспечения ЭВМ. Сегодня только очень малая часть программного обеспечения, требующая особой эффективности, разрабатывается с помощью ассемблеров. В настоящее время имеет применение довольно большое количество языков программирования… Читать ещё >

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

В настоящее время языки высокого уровня стали основным средством разработки программ. Поэтому компиляторы составляют существенную часть системного программного обеспечения ЭВМ. Сегодня только очень малая часть программного обеспечения, требующая особой эффективности, разрабатывается с помощью ассемблеров. В настоящее время имеет применение довольно большое количество языков программирования. Наряду с традиционными языками, такими, например, как Фортран, широкое распространение получили так называемые «универсальные» языки (Паскаль, Си, Модула-2, Ада) и др., а также некоторые специализированные (например, язык обработки списочных структур Лисп). Кроме того, большое распространение получили языки, связанные с узкими предметными областями, такие, как входные языки пакетов прикладных программ.

Для ряда названных языков имеется довольно много реализаций для различных операционных систем и архитектур ЭВМ.

В рамках традиционных последовательных машин развивается большое число различных направлений архитектур. Примерами могут служить архитектуры CISC, RISC. Такие ведущие фирмы, как Intel, Motorola, Sun, начинают переходить на выпуск машин с RISC-архитектурами. Естественно, для каждой новой системы команд требуется полный набор новых компиляторов с распространенных языков.

Поэтому важную роль компиляторов в современном системном ПО для ЭВМ невозможно переоценить.

В данной курсовой работе делается попытка создания простого интерпретатора с целью изучения принципов строения и работы этого вида системного ПО.

1. Техническое задание

В данной курсовой работе требуется:

Создать программу-интерпретатор, способную получать на входе текстовый файл (в формате ASCII или ANSI) с текстом программы. На выходе — выводит на экран результаты вычислений, определяемых программистом. Если входная программа содержит ошибку — сообщение о типе ошибки.

Интерпретатор должен воспринимать и обрабатывать следующие инструкции:

а) объявление переменной с одновременным присвоением ей начального значения

Имя Переменной = значение или Имя Переменной = выражение

Значение переменной задается вещественным числом в десятичной системе счисления. Например, X=0.06

Выражения записываются по правилам, Например, F=-X/0.01

б) вывод результатов на экран

PRINT (Имя Переменной) или PRINT (выражение)

Например, PRINT (X) и PRINT (X+F)

в) Операндами выражения могут быть вещественные числа и имена объявленных ранее переменных. В выражении допускаются следующие операторы:

+ сумма;

— разность, унарный минус;

* произведение;

/ частное;

ABS (…) модуль числа;

^ возведение в степень (степень выражается целым числом 0);

SQRT (…) квадратный корень;

EXP (…) экспонента;

LN (…) натуральный логарифм.

Порядок выполнения операций может регулироваться скобками ().

Инструкции в тексте программы разделяются точкой с запятой, либо каждая инструкция — с новой строки.

2. Разработка грамматики

Список допустимых лексем (слов языка).

Допустимыми являются:

— имя переменной <�имя переменной> = L; (L — буква, C — цифра)

— зарезервированные слова <�зарезервированные слова> = <'print', 'abs', 'sqrt', 'exp', 'ln'>

— используемые символы <�символы> = <'+', '-', '/', '*', '(', ')', '.', '^'>

Все буквы — маленькие латинские.

Программа состоит из двух основных блоков, парсера и лексера.

Парсер отвечает за разбиение на токены, а лексер анализирует токены, и в зависимости от содержимого выполняет над ними действия.

3. Описание программы

Программа-интерпретатор выполнена с использованием среды разработки Borland С++ 6.0 и представляет собой интерактивную оболочку, позволяющую загружать исходный ASCII-текст, содержащий программу, написанную в соответствии с синтаксисом входного языка.

интерпретатор текстовый файл лексема

3.1 Интерфейс программы

Интерфейс программы состоит из формы (Form1), также ее можно считать диалоговым окном между пользователем и программой выполняющей вычисление по заданному алгоритму.

На форме также расположены Panel1, RichEdit1, MainMenu1 и OpenDialog1.

Свойства для компонентов

Panel1:

— Высота (Height) = 289

— Ширина (Width) = 449

Form1:

— AutoSize = true

— Caption = Интерпретатор арифметики вещественных чисел

MainMenu1:

Состоит из следующих пунктов

— Файл

— Открыть

— Выход

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

Открыть Ctrl+O

Выход Ctrl+X

Выполнить F9

Структура меню Для того чтобы задать каждому пункту меню определенную комбинацию быстрых клавиш необходимо в окне Object Inspector компонента MainMenu1 выбрать необходимый пункт меню и в поле ShortCut выбрать необходимую комбинацию.

Из-за того что мы используем RichEdit1 наше приложение будет интерактивным, а именно, после того как код программы будет загружен в окне нашего приложения в него можно будет вносить изменения и дополнять его.

OpenDialog1:

Для того чтобы во время открытии текстового (txt) файла нам не мешались файлы с другими расширениями, нам необходимо установить фильтр для данного компонента OpenDialog1. В окне Object Inspector для OpenDialog1 в пункте Filter нажимаем на кнопку и устанавливаем необходимые фильтры.

*.txt — Отображать файлы с расширением TXT

*.* - Отображать все файлы Результатом обработки текста программы является вывод в окне интерпретатора результата вычисления, либо сообщения об ошибке.

3.2 Листинг программы

Unit1.cpp

#include

#pragma hdrstop

#include «Unit1.h»

//—————————————————————————————————————;

#pragma package (smart_init)

#pragma resource «*.dfm»

TForm1 *Form1;

//—————————————————————————————————————;

__fastcall TForm1: TForm1(TComponent* Owner)

: TForm (Owner)

{

}

//—————————————————————————————————————;

void __fastcall TForm1: Open1Click (TObject *Sender)

{

OpenDialog1->Options.Clear ();

OpenDialog1->Options << ofAllowMultiSelect << ofFileMustExist;

if (OpenDialog1->Execute ())

RichEdit1->Lines->LoadFromFile (OpenDialog1->FileName);

}

//—————————————————————————————————————;

void __fastcall TForm1: Calculate1Click (TObject *Sender)

{

char *code;

char buffer[1024];

code = RichEdit1->Lines->GetText ();

CodeBuffer *cb = parser_codebuffer_new (code);

/* Вычислить выражения */

ParserVal v1 = parser_evaluate (cb);

/* Напечатать результат выполнения операции */

RichEdit1->Lines->Add ((v1.error));

/* Важно: Обязательно освободить массив значений v1 */

parser_value_free (&v1);

/* Освободить буфер кода и список переменных */

parser_codebuffer_destroy (cb);

/* И освободить cb */

free (cb);

}

void __fastcall TForm1: Variable_print_all (ParserVariable *variables[])

{

if (!variables) return;

size_t i;

char buffer[1024];

for (i=0; i< MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i]) continue;

ParserVariable *var = variables[i];

switch (var->val.type)

{

case TOK_NUMERIC:

sprintf (buffer," %s=%sn", var->name, parser_value_show_as_string (&var->val));

RichEdit1->Lines->Add (buffer);

break;

case TOK_STRING:

sprintf (buffer," %s=%sn", var->name, var->val.s);

RichEdit1->Lines->Add (buffer);

break;

default:

sprintf (buffer, «%s Имеет неизвестный тип переменной%d.n», var->name, var->val.type);

RichEdit1->Lines->Add (buffer);

break;

}

}

}

//—————————————————————————————————————;

void __fastcall TForm1: Exit1Click (TObject *Sender)

{

Close ();

}

Parser.cpp

#include «lexer.h»

#include «parser.h»

#include «Unit1.h»

#ifndef M_PI

#define M_PI 3.14 159 265 358 979 324

#endif

ParserVal parser_statements (CodeBuffer *cb);

ParserVal parser_assign (CodeBuffer *cb);

void do_sqrt (ParserVal *a, int b);

void do_abs (ParserVal *, int);

void do_exp (ParserVal *, int);

void do_ln (ParserVal *, int);

void do_pow (ParserVal *, int);

void do_integer (ParserVal *, int);

void do_round (ParserVal *, int);

void do_fraction (ParserVal *, int);

void do_boolean_str (int oper, ParserVal *v1, ParserVal *v2);

void do_boolean (int oper, ParserVal *v1, ParserVal *v2);

void do_math (int oper, ParserVal *v1, ParserVal *v2);

void do_unary (int oper, ParserVal *v1);

void do_power (ParserVal *v1, ParserVal *v2);

void parser_do_print (ParserVal *, int);

BuiltinFunction g_function_table[] = {

/* Массив внутренних функций */

{" sqrt", 1, do_sqrt},

{" abs", 1, do_abs},

{" exp", 1, do_exp},

{" ln", 1, do_ln},

{" pow", 2, do_pow},

{" print", 1, parser_do_print},

{" int", 1, do_integer},

{" modf", 1, do_fraction}

};

BuiltinFunction *lookup_builtin_function (char *name);

char *builtin_function_arg_text (BuiltinFunction *func);

size_t parser_strlen (char *s);

ParserVal execute_builtin_function (CodeBuffer *cb, BuiltinFunction *func);

ParserVal parser_bool_or (CodeBuffer *cb);

ParserVal parser_bool_and (CodeBuffer *cb);

ParserVal parser_bool1(CodeBuffer *cb);

ParserVal parser_bool2(CodeBuffer *cb);

ParserVal parser_bool3(CodeBuffer *cb);

ParserVal parser_level1(CodeBuffer *cb);

ParserVal parser_level2(CodeBuffer *cb);

ParserVal parser_level3(CodeBuffer *cb);

ParserVal parser_level4(CodeBuffer *cb);

ParserVal parser_level5(CodeBuffer *cb);

void parser_error (CodeBuffer *cb, char *msg, int opt);

void parser_convert_to_numeric (ParserVal *v);

void parser_convert_to_string (ParserVal *v);

int is_numeric (ParserVal *v);

int is_string (ParserVal *v);

int str_icmp (char *s1, char *s2);

void parser_add_strings (ParserVal *v1, ParserVal *v2);

double get_int_part (double x);

double round_num (double d, unsigned int dec_places);

/* Хранение глобальных tokenов для функций которые не анализируют их */

TokenRec currToken;

ParserVal parser_evaluate (CodeBuffer *cb)

{

/* Начало parsingа для col 0, line 1 */

cb->curr_pos = 0;

cb->line_num = 1;

memset (cb->char_backbuf, '', MAX_CHAR_BACKBUF_LEN);

cb->tok_backbuf_count = 0;

parser_variable_add_standard_constants (cb);

ParserVal v1 = parser_statements (cb);

/* Необходимо освободить v1 после использования. Вызов parser_value_free (&v1); */

return v1;

}

void parser_do_print (ParserVal *v, int arg_count){

char buffer[1024];

parser_convert_to_numeric (v);

v->s = parser_format_string («Результат:%g», v->d);

Form1->RichEdit1->Lines->Add (v->s);

return;

}

ParserVal parser_statements (CodeBuffer *cb)

{

ParserVal v1;

parser_value_init_to_numeric (&v1, 0.0);

lexer_get_token (cb, &currToken);

while (currToken.type ≠ TOK_EOF)

{

v1 = parser_assign (cb);

if (v1.error)

{

parser_error (cb, v1. error, TRUE);

return v1;

}

switch (v1.type)

{

case TOK_STRING:

break;

case TOK_NUMERIC:

break;

case 'n':

/* Пустая инструкция */

break;

}

}

/* Необходимо освободить V1 после использования.

parser_value_free (&v1);

*/

return v1;

}

ParserVal parser_assign (CodeBuffer *cb)

{

ParserVal v1;

ParserVariable **variables = parser_variable_create_list ();

/* Текущий token идентификатор, а следующий token знак '=' */

while (currToken.type == TOK_IDENT && lexer_lookahead (cb, '=', TRUE/*remove it*/))

{

ParserVariable *var = (ParserVariable *)calloc (1, sizeof (ParserVariable));

var->name = parser_format_string («%s», currToken. str);

parser_value_init_to_numeric (&var->val, 0.0);

/* Добавить переменную в список */

parser_variable_add_to_list (variables, var);

lexer_get_token (cb, &currToken);

}

/* Анализ и оценка значения */

v1 = parser_bool1(cb);

if (!v1.error)

{

size_t i;

for (i = 0; i < MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i]) continue;

parser_value_copy (&v1, &variables[i]->val);

parser_variable_add_to_list (cb->variable_list, variables[i]);

}

}

free (variables);

return v1;

}

ParserVal parser_bool1(CodeBuffer *cb)

{

int oper;

ParserVal v1 = parser_bool2(cb);

oper = currToken. type;

/* Логический оператор: '&&' Логическое AND */

while (oper == TOK_AND)

{

DEBUG_PAR2(«ОТЛАДКА parser_bool1 (&&): Оператор=%c Значение v1=%sn», oper, parser_value_show_as_string (&v1));

lexer_get_token (cb, &currToken);

ParserVal v2 = parser_bool2(cb);

do_boolean (oper, &v1, &v2);

/* Free v2 */

parser_value_free (&v2);

oper = currToken. type;

if (v1.error) break;

}

return v1;

}

ParserVal parser_bool2(CodeBuffer *cb)

' Логическое OR */

while (oper == TOK_OR)

DEBUG_PAR2(«ОТЛАДКА parser_bool2 (

return v1;

ParserVal parser_bool3(CodeBuffer *cb)

{

int oper;

ParserVal v1 = parser_level1(cb);

oper = currToken. type;

/* Логический оператор: ==, >, >=, <, <= */

while (oper == TOK_EQ || oper == TOK_GT || oper == TOK_LT || oper == TOK_LE || oper == TOK_GE)

{

DEBUG_PAR2(«ОТЛАДКА parser_bool3 (==, >, >=, <, <=): оператор=%c Значение v1=%sn», oper, parser_value_show_as_string (&v1));

lexer_get_token (cb, &currToken);

ParserVal v2 = parser_level1(cb);

do_boolean (oper, &v1, &v2);

/* Free v2 */

parser_value_free (&v2);

oper = currToken. type;

if (v1.error) break;

}

return v1;

}

ParserVal parser_level1(CodeBuffer *cb)

{

int oper;

ParserVal v1 = parser_level2(cb);

oper = currToken. type;

/* Математические операторы: +, — */

while (oper == TOK_PLUS || oper == '-')

{

DEBUG_PAR2(«ОТЛАДКА parser_level1 (+/-): оператор=%c Значение v1=%sn», oper, parser_value_show_as_string (&v1));

lexer_get_token (cb, &currToken);

ParserVal v2 = parser_level2(cb);

do_math (oper, &v1, &v2);

/* Free v2 */

parser_value_free (&v2);

oper = currToken. type;

if (v1.error) break;

}

return v1;

}

ParserVal parser_level2(CodeBuffer *cb)

{

int oper;

ParserVal v1 = parser_level3(cb);

oper = currToken. type;

// *, /

while (oper == TOK_MUL || oper == TOK_DIV)

{

DEBUG_PAR2(«ОТЛАДКА parser_level2: оператор=%c Значение v1=%sn», oper, parser_value_show_as_string (&v1));

lexer_get_token (cb, &currToken);

ParserVal v2 = parser_level3(cb);

do_math (oper, &v1, &v2);

/* Free v2 */

parser_value_free (&v2);

oper = currToken. type;

if (v1.error) break;

}

return v1;

}

ParserVal parser_level3(CodeBuffer *cb)

{

ParserVal v1 = parser_level4(cb);

/* '^' Экспоненциальный: 23 = 8. */

if (currToken.type == TOK_EXP)

{

lexer_get_token (cb, &currToken);

printf («parser_level3: Оператор=%c Значение v1=%sn», TOK_EXP, parser_value_show_as_string (&v1));

DEBUG_PAR2(«ОТЛАДКА parser_level3: Оператор=%c Значение v1=%sn», TOK_EXP, parser_value_show_as_string (&v1));

ParserVal v2 = parser_level3(cb); /* Recursively */

do_power (&v1, &v2);

/* Free v2 */

parser_value_free (&v2);

}

return v1;

}

ParserVal parser_level4(CodeBuffer *cb)

{

int oper;

oper = 0;

/* Унарный +/- пример. (+3) + -3. */

if (currToken.type == '-' || currToken. type == '+')

{

oper = currToken. type;

lexer_get_token (cb, &currToken);

}

ParserVal v1 = parser_level5(cb);

if (oper ≠ 0)

{

DEBUG_PAR2(«ОТЛАДКА parser_level4 (унарный +/-): Оператор=%c Значение v1=%sn», oper, parser_value_show_as_string (&v1));

do_unary (oper, &v1);

}

return v1;

}

ParserVal parser_level5(CodeBuffer *cb)

{

TokenRec val;

ParserVal v1; //= {.type=TOK_NUMERIC, {.d=0.0},.error=NULL};

v1.type=TOK_NUMERIC;

v1.d=0.0;

v1.error=NULL;

/* Сохранение текущего типа tokenа */

val = currToken;

switch (currToken.type)

{

/* '(' Выражение ')'.

Пример. «((2 + 5) * 6)»

*/

case TOK_PAROPEN:

lexer_get_token (cb, &currToken);

v1 = parser_bool1(cb);

/* С правой скобкой ')'? */

if (currToken.type ≠ TOK_PARCLOSE)

{

/* Отсутствие правая скобка ')' */

v1.error = parser_format_string («Отсутствует правая скобка ')'.»);

}

lexer_get_token (cb, &currToken);

break;

case TOK_NUMERIC:

v1.type = TOK_NUMERIC;

v1.d = currToken.val.d;

lexer_get_token (cb, &currToken);

break;

case TOK_IDENT:

{

/* Это встроенная функция? */

BuiltinFunction *func = lookup_builtin_function (currToken.str);

if (func)

{

/* Проверка открытия '(' */

if (!lexer_lookahead (cb, '(', TRUE/*remove it*/))

{

/* Отсутствие '(' */

v1.error = parser_format_string («Отсутствует левая скобка '(' у функции%s.n», func->name);

goto l_end_ident;

}

lexer_get_token (cb, &currToken);

v1 = execute_builtin_function (cb, func);

/* С закрытием ')'? */

if (currToken.type ≠ TOK_PARCLOSE)

{

/* Отсутствие ')' */

v1.error = parser_format_string («Отсутствует правая скобка ')'. получен знак '%s'.», currToken. str);

}

}

else

{ /* Это переменная */

int i = parser_variable_find (cb->variable_list, currToken. str);

if (i > -1)

{

ParserVariable *var = cb->variable_list[i];

parser_value_copy (&var->val, &v1);

}

else

{

/* Неизвестная переменная или идентификатор */

v1.error = parser_format_string («Неизвестный идентификатор '%s'.», currToken. str);

}

}

l_end_ident:

lexer_get_token (cb, &currToken);

}

break;

case TOK_STRING:

/* Строка цитаты «или ' */

parser_value_set_to_string (&v1, currToken. str);

lexer_get_token (cb, &currToken);

break;

case 'n':

case ';':

/* Конец или пустой оператор */

v1.type = 'n';

lexer_get_token (cb, &currToken);

break;

default:

v1.error = parser_format_string («Неизвестный знак '%s'», currToken. str);

lexer_get_token (cb, &currToken);

}

DEBUG_PAR2(«ОТЛАДКА parser_level5: type=%d Значение v1=%s.n», val. type, parser_value_show_as_string (&v1));

return v1;

}

void do_boolean_str (int oper, ParserVal *v1, ParserVal *v2)

{

parser_convert_to_string (v1);

parser_convert_to_string (v2);

int ret = strcmp (v1->s, v2->s);

switch (oper)

{

/* v1 == v2 */

case TOK_EQ:

parser_value_set_to_numeric (v1, (double)(ret == 0));

break;

/* v1 > v2 */

case TOK_GT:

parser_value_set_to_numeric (v1, (double)(ret > 0));

break;

/* v1 >= v2 */

case TOK_GE:

parser_value_set_to_numeric (v1, (double)(ret > 0 || ret == 0));

break;

/* v1 < v2 */

case TOK_LT:

parser_value_set_to_numeric (v1, (double)(ret < 0));

break;

/* v1 <= v2 */

case TOK_LE:

parser_value_set_to_numeric (v1, (double)(ret < 0 || ret == 0));

break;

/* v1 && v2 */

case TOK_AND:

if (!(parser_strlen (v1->s) && parser_strlen (v2->s)))

{

/* Set v1 to zero (FALSE) */

parser_value_free (v1);

}

break;

/* v1 || v2 */

case TOK_OR:

if (!parser_strlen (v1->s))

{

/* Copy v2 to v1 */

parser_value_free (v1);

parser_value_copy (v2, v1);

}

break;

}

}

void do_boolean (int oper, ParserVal *v1, ParserVal *v2)

{

if (is_string (v1) || is_string (v2))

{

do_boolean_str (oper, v1, v2);

return;

}

parser_convert_to_numeric (v1);

parser_convert_to_numeric (v2);

switch (oper)

{

/* v1 == v2 */

case TOK_EQ:

v1->d = (v1->d == v2->d);

break;

/* v1 > v2 */

case TOK_GT:

v1->d = (v1->d > v2->d);

break;

/* v1 >= v2 */

case TOK_GE:

v1->d = (v1->d >= v2->d);

break;

/* v1 < v2 */

case TOK_LT:

v1->d = (v1->d < v2->d);

break;

/* v1 <= v2 */

case TOK_LE:

v1->d = (v1->d <= v2->d);

break;

/* v1 && v2 */

case TOK_AND:

if (v1->d == 0.0 || v2->d == 0.0)

{

/* Set v1 to zero (FALSE) */

v1->d = 0.0;

}

break;

/* v1 || v2 */

case TOK_OR:

if (v1->d == 0.0)

{

/* Copy v2 to v1 */

v1->d = v2->d;

}

break;

}

}

void do_math (int oper, ParserVal *v1, ParserVal *v2)

{

if (oper == '+')

{

if (is_string (v1) || is_string (v2))

{

parser_add_strings (v1, v2);

}

else

{

v1->d = v1->d + v2->d;

}

return;

}

if ((is_string (v1) || is_string (v2)))

{

v1->error = parser_format_string («Строка не может принять математический оператор '%c'.», oper);

return;

}

parser_convert_to_numeric (v1);

parser_convert_to_numeric (v2);

switch (oper)

{

case '-':

v1->d = v1->d — v2->d;

break;

case '*':

v1->d = v1->d * v2->d;

break;

case '/':

if (v2->d ≠ 0.0)

v1->d = v1->d / v2->d;

else

{

v1->error = parser_format_string («Деление на ноль.»);

}

break;

}

}

void do_power (ParserVal *v1, ParserVal *v2)

{

parser_convert_to_numeric (v1);

parser_convert_to_numeric (v2);

if (is_numeric (v1) && is_numeric (v2))

{

double d = v1->d;

long i;

for (i=1; i<(long)v2->d; i++) v1->d *= d;

}

else

{

v1->error = parser_format_string («Строка не может принять экспоненциальный оператор '^'.»);

}

}

void do_unary (int oper, ParserVal *v)

{

parser_convert_to_numeric (v);

if (!is_numeric (v))

{

v->error = parser_format_string («Строка не может принять унарный '%c' оператор.», oper);

return;

}

v->d = -v->d;

}

int is_numeric (ParserVal *v)

{

return v->type == TOK_NUMERIC;

}

int is_string (ParserVal *v)

{

return v->type == TOK_STRING;

}

void parser_convert_to_numeric (ParserVal *v)

{

if (v->type == TOK_NUMERIC) return;

/* ATM we do not convert string to numeric value */

}

void parser_convert_to_string (ParserVal *v)

{

/* Преобразование числового значения в строку */

if (v->type == TOK_STRING) return;

/* Value as string picture */

char *p = parser_value_show_as_string (v);

v->s = (char*) calloc (MAX_NUMERIC_LEN, sizeof (char));

size_t len = min (parser_strlen (p), MAX_NUMERIC_LEN-1);

if (len)

strncpy (v->s, p, len);

*(v->s + len) = '';

v->type = TOK_STRING;

}

char *parser_value_show_as_string (ParserVal *v)

{

/* Static char buffer, return pointer to it */

static char buf[MAX_TOKEN_LEN];

/* Это строка? */

if (v->type == TOK_STRING)

{

size_t len = min (parser_strlen (v->s), MAX_TOKEN_LEN);

strncpy (buf, v->s, len);

*(buf + len) = '';

return buf;

}

/* Это числовое */

double ceil_diff = ceil (v->d) — v->d;

double floor_diff = v->d — floor (v->d);

double diff, res;

if (ceil_diff < floor_diff)

{

diff = ceil_diff;

res = ceil (v->d);

}

else

{

diff = floor_diff;

res = floor (v->d);

}

if (diff < 0.0009)

sprintf (buf, «%ld», (long)res); /* Отобразить как целое */

else

sprintf (buf, «%.3f», v->d); /* Отобразить как действительное десятичное число */

return buf;

}

double parser_value_as_numeric (ParserVal *v)

{

if (v->type == TOK_NUMERIC)

return v->d;

else

return 0.0;

}

char *parser_value_as_string (ParserVal *v)

{

/* Do not free the value.

It points to a static char buffer.

*/

return parser_value_show_as_string (v);

}

int parser_value_as_boolean (ParserVal *v)

{

if (v->type == TOK_NUMERIC)

return (int)v->d ≠ 0;

if (str_icmp (v->s, «Истина»))

return TRUE;

if (str_icmp (v->s, «1»))

return TRUE;

if (str_icmp (v->s, «Лож»))

return FALSE;

if (str_icmp (v->s, «0»))

return FALSE;

return FALSE;

}

void parser_add_strings (ParserVal *v1, ParserVal *v2)

{

parser_convert_to_string (v1);

parser_convert_to_string (v2);

size_t len1 = min (parser_strlen (v1->s), MAX_TOKEN_LEN);

size_t len2 = min (parser_strlen (v2->s), MAX_TOKEN_LEN);

char *p = (char*)calloc (len1 + len2 + 1, sizeof (char));

if (len1)

strncpy (p, v1->s, len1);

if (len2)

strncpy (p + len1, v2->s, len2);

*(p + len1 + len2) = '';

free (v1->s);

v1->s = p;

}

/* ************************** */

/* Numeric and string values */

/* ************************** */

void parser_value_set_to_numeric (ParserVal *v, double d)

{

parser_value_free (v);

parser_value_init_to_numeric (v, d);

}

void parser_value_set_to_string (ParserVal *v, char *s)

{

parser_value_free (v);

parser_value_init_to_string (v, s);

}

void parser_value_init_to_numeric (ParserVal *v, double d)

{

v->d = d;

v->type = TOK_NUMERIC;

v->error = NULL;

}

void parser_value_init_to_string (ParserVal *v, char *s)

{

size_t len = min (parser_strlen (s), MAX_TOKEN_LEN);

v->s = (char*)calloc (len + 1, sizeof (char));

if (len)

strncpy (v->s, s, len);

*(v->s + len) = '';

v->type = TOK_STRING;

v->error = NULL;

}

void parser_value_free (ParserVal *v)

{

parser_value_delete (v);

}

void parser_value_copy (ParserVal *from_v, ParserVal *to_v)

{

*to_v = *from_v;

if (from_v->type ≠ TOK_STRING) return;

size_t len = min (parser_strlen (from_v->s), MAX_TOKEN_LEN);

to_v->s =(char*) calloc (len + 1, sizeof (char));

if (len)

strncpy (to_v->s, from_v->s, len);

*(to_v->s+len) = '';

}

void parser_value_delete (ParserVal *v)

{

if (v->type == TOK_STRING)

{

/* Free string value */

if (v->s) free (v->s);

v->s = NULL;

}

/* Free error */

if (v->error) free (v->error);

v->error = NULL;

/*

Let it keep the type.

*/

}

void do_sqrt (ParserVal *v, int arg_count)

{

/* Return sqrt (v[0]) in v[0] */

v[0]. d = sqrt (v[0]. d);

}

void do_abs (ParserVal *v, int arg_count)

{

/* Return abs (v[0]) in v[0]. */

v[0]. d = fabs (v[0]. d);

}

void do_exp (ParserVal *v, int arg_count)

{

/* Return exp (v[0]) in v[0]. */

v[0]. d = exp (v[0]. d);

}

void do_ln (ParserVal *v, int arg_count)

{

/* Return log (v[0]) in v[0]. */

v[0]. d = log (v[0]. d);

}

void do_pow (ParserVal *v, int arg_count)

{

/* Return pow (v[0], v[1]) in v[0]. */

v[0]. d = pow (v[0]. d, v[1]. d);

}

void do_integer (ParserVal *v, int arg_count)

{

/* Return integer (whole part of) v[0] in v[0]. */

modf (v[0]. d, &v[0]. d/*int part*/);

}

void do_fraction (ParserVal *v, int arg_count)

{

/* Return fraction (decimal part of) v[0] in v[0]. */

double int_part;

v[0]. d/*fraction*/ = modf (v[0]. d, &int_part);

}

void do_round (ParserVal *v, int arg_count)

{

/* Round v[0] to nearest n decimal. n = {0…10}.

v[1] contains n. Returns the rounded value in v[0].

*/

/* TODO: Find a better way to do this ! */

static char buf[MAX_NUMERIC_LEN];

static char format[MAX_NUMERIC_LEN];

sprintf (format, «%%.%df», (int)v[1]. d);

sprintf (buf, format, v[0]. d);

v[0].d = atof (buf);

}

BuiltinFunction *lookup_builtin_function (char *name)

{

int i;

for (i=0; i< sizeof (g_function_table)/sizeof (g_function_table[0]); i++)

{

if (!strcmp (g_function_table[i]. name, name))

return &g_function_table[i];

}

return NULL;

}

ParserVal execute_builtin_function (CodeBuffer *cb, BuiltinFunction *func)

{

ParserVal v[MAX_FUNC_ARGS];

int i;

for (i=0; i< MAX_FUNC_ARGS; i++)

parser_value_init_to_numeric (&v[i], 0.0);

if (!func) return v[0];

int arg_count = 0;

while (func->num_args)

{

v[arg_count] = parser_bool1(cb);

arg_count++;

if (arg_count >= func->num_args || arg_count >= MAX_FUNC_ARGS) break;

if (func->num_args == (int)'*')

{

if (currToken.type == ',')

{

/* Removed comma */

; /* ok */

}

else if (currToken.type == ')')

{

break;

}

else

{

v[0]. error = parser_format_string («Missing ',' or ')' at function%s.», func->name);

return v[0];

}

}

else

{

/* Remove comma between expressions */

if (currToken.type ≠ TOK_COMMA)

{

char *p = builtin_function_arg_text (func);

v[0]. error = parser_format_string («Missing ',' at function%s. Function%s takes%s arguments.», func->name, func->name, p);

free (p);

return v[0];

}

}

/* Next token */

lexer_get_token (cb, &currToken);

}

if (arg_count == 0)

{

char *p = builtin_function_arg_text (func);

v[0]. error = parser_format_string («Не заданы аргументы. Функция%s имеет%s аргумент (ы).», func->name, p);

free (p);

return v[0];

}

func->func (v, arg_count);

return v[0];

}

char *builtin_function_arg_text (BuiltinFunction *func)

{

char *p;

if (func->num_args == '*')

p = parser_format_string («До%d», MAX_FUNC_ARGS);

else

p = parser_format_string («%d», func->num_args);

/* You should free () the value after usage */

return p;

}

char *parser_copy_string (char *s)

{

size_t len = min (parser_strlen (s), MAX_TOKEN_LEN);

char *tmp = (char*)calloc (len+1, sizeof (char));

if (len)

strncpy (tmp, s, len);

*(tmp+len) = '';

return tmp;

}

char *parser_quote_string (char *s)

{

size_t len = min (parser_strlen (s), MAX_TOKEN_LEN);

char *tmp;

if (len > 0 && (*s == '" ' || *s == '''))

{

return parser_copy_string (s);

}

tmp =(char*) calloc (len + 3/* «+ + «*/, sizeof (char));

*tmp = '" ';

if (len)

strncpy (tmp+1, s, len);

*(tmp+len+1) = '" ';

*(tmp+len+2) = '';

return tmp;

}

size_t parser_strlen (char *s)

{

if (!s) return (size_t)0;

return strlen (s);

}

char *parser_format_string (const char *fmt,…)

{

char *msg = (char*)calloc (MAX_TOKEN_LEN, sizeof (char));

va_list args;

va_start (args, fmt);

vsprintf (msg, fmt, args);

va_end (args);

return msg;

}

void parser_error (CodeBuffer *cb, char *msg, int opt)

{

char buffer[1024];

if (opt && cb)

sprintf (buffer, «Ошибка парсера в строке%d:%sn», lexer_line_num (cb), msg);

else

sprintf (buffer, «Ошибка парсера%sn», msg);

Form1->RichEdit1->Lines->Add (buffer);

}

/* Переменные */

void parser_variable_add_value (CodeBuffer *cb, char *name, ParserVal *value)

{

if (value->type == TOK_STRING)

parser_variable_add_string_var (cb, name, value->s, FALSE/*quoted*/);

else

parser_variable_add_numeric_var (cb, name, value->d);

}

void parser_variable_add_numeric_var (CodeBuffer *cb, char *name, double val)

{

if (!(cb && name)) return;

ParserVariable *var = parser_variable_create_new (name);

parser_value_init_to_numeric (&var->val, val);

parser_variable_add_to_list (cb->variable_list, var);

}

void parser_variable_add_string_var (CodeBuffer *cb, char *name, char *val, int quoted)

{

if (!(cb && name)) return;

ParserVariable *var = parser_variable_create_new (name);

/* «Цитировать»? */

if (quoted)

{

char *tmp = parser_quote_string (val);

parser_value_init_to_string (&var->val, tmp);

free (tmp);

}

else

parser_value_init_to_string (&var->val, val);

parser_variable_add_to_list (cb->variable_list, var);

}

void parser_variable_add_standard_constants (CodeBuffer *cb)

{

if (!cb) return;

}

ParserVariable **parser_variable_create_list ()

{

/* Создать пустой список переменных */

ParserVariable **list;

list = (ParserVariable **)calloc (MAX_VARIABLE_LIST_LEN, sizeof (ParserVariable));

return list;

}

ParserVariable *parser_variable_create_new (char *name)

{

ParserVariable *var = (ParserVariable *)calloc (1, sizeof (ParserVariable));

var->name = parser_format_string («%s», name);

/* Присвоить 0.0 (TOK_NUMERIC) */

parser_value_init_to_numeric (&var->val, 0.0);

return var;

}

int parser_variable_add_to_list (ParserVariable *variables[], ParserVariable *var)

{

int i;

i = parser_variable_find (variables, var->name);

if (i > -1)

{ /* Обновление существующей переменной */

parser_variable_delete (variables[i]);

variables[i] = var;

return i;

}

/* Добавление новой переменной */

for (i = 0; i< MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i])

{

variables[i] = var;

return i;

}

}

parser_error (NULL, «Список переменных переполнен. n», FALSE);

return -1;

}

int parser_variable_find (ParserVariable *variables[], char *name)

{

int i;

for (i=0; i< MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i]) break;

if (!strcmp (name, variables[i]->name)) return i;

}

return -1;

}

void parser_variable_print_all (ParserVariable *variables[])

{

if (!variables) return;

size_t i;

for (i=0; i< MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i]) continue;

ParserVariable *var = variables[i];

switch (var->val.type)

{

case TOK_NUMERIC:

printf («%s=%s (numeric).n», var->name, parser_value_show_as_string (&var->val));

break;

case TOK_STRING:

printf («%s=%s (string).n», var->name, var->val.s);

break;

default:

printf («%s Неизвестный тип переменной%d.n», var->name, var->val.type);

break;

}

}

}

char *parser_variable_get_debug_text (ParserVariable *variables[])

{

/* Return a long string (text) with variable names and values.

Usefull for inspection and debugging.

*/

if (!variables) return NULL;

char *text = parser_format_string («Переменные:n»);

size_t i;

for (i=0; i< MAX_VARIABLE_LIST_LEN; i++)

{

if (!variables[i]) continue;

ParserVariable *var = variables[i];

char *tmp;

tmp = NULL;

switch (var->val.type)

{

case TOK_NUMERIC:

tmp = parser_format_string («%s=%s (numeric).n», var->name, parser_value_show_as_string (&var->val));

break;

case TOK_STRING:

tmp = parser_format_string («%s=%s (string).n», var->name, var->val.s);

break;

default:

tmp = parser_format_string («%s Неизвестный тип переменной%d.n», var->name, var->val.type);

break;

}

if (tmp)

{

char *tmp2 = parser_format_string («%s%s», text, tmp);

free (text);

text = tmp2;

}

free (tmp);

}

return text;

}

void parser_variable_delete (ParserVariable *var)

{

if (!var) return;

parser_value_delete (&var->val);

free (var->name);

var->name = NULL;

}

void parser_variable_delete_all (ParserVariable *variables[])

{

if (!variables) return;

size_t i;

for (i=0; i< MAX_VARIABLE_LIST_LEN; i++)

{

parser_variable_delete (variables[i]);

}

free (variables);

variables = NULL;

}

int str_icmp (char *s1, char *s2)

{

return strcmp (s1, s2);

}

Lexer.cpp

#include

#include

#include

#include

#include «lexer.h»

#include «parser.h»

int lexer_lookahead_token (CodeBuffer *cb, char *_token, int _remove/*Удалить если нашли?*/, int _eat_nl/*Искать переводы строки? 'n' ?*/)

{

TokenRec tok;

int ret = FALSE;

while (1)

{

lexer_get_token (cb, &tok);

if (tok.type == TOK_EOF) break;

ret = (!strcmp (tok.str, _token));

if (!ret && (_eat_nl && tok. type == 'n')) continue;

if (!ret)

{

lexer_put_token_back (cb, &tok);

}

else

{

if (!_remove)

lexer_put_token_back (cb, &tok);

}

break;

}

return ret;

}

void lexer_put_token_back (CodeBuffer *cb, TokenRec *_tokRec)

{

if (cb->tok_backbuf_count >= MAX_TOKEN_BACKBUF_LEN-1)

{

lexer_error (cb, «Буфер Tokenа переполнен. n»);

}

cb->tok_backbuf[cb->tok_backbuf_count] = *_tokRec;

cb->tok_backbuf_count++;

}

int lexer_get_token_from_backbuf (CodeBuffer *cb, TokenRec *_tokRec)

{

/* Содержит буфер данные? */

if (cb->tok_backbuf_count > 0)

{

cb->tok_backbuf_count—;

*_tokRec = cb->tok_backbuf[cb->tok_backbuf_count];

/* Взяли данные из буфера */

return TRUE;

}

else

{ /* Обнулить строку */

*_tokRec->str = '';

_tokRec->type = TOK_EOF;

}

/* Буфер был пустой */

return FALSE;

}

int lexer_get_token (CodeBuffer *cb, TokenRec *_tokRec)

{

/* Читаем следующий Token из буфера */

char ch;

char ch2 = 0;

char *cPtr;

static char buf[MAX_TOKEN_LEN];

/* Очистить буфер tokenов */

memset (_tokRec, sizeof (TokenRec), '');

*buf = *(buf+1) = *(buf+2) = '';

*(_tokRec->str) = *(_tokRec->str+1) = *(_tokRec->str+2) = '';

_tokRec->type = TOK_EOF;

/* Проверка буфера tokenов */

if (lexer_get_token_from_backbuf (cb, _tokRec))

{

return _tokRec->type;

}

/* Выбираем следующий символ, удаляем пробелы, комментарии */

ch = lexer_get_charEx (cb);

/* Проверяем является ли символ оператором */

switch (ch)

{

case '=':

_tokRec->type = TOK_ASSIGN;

/* == */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_EQ;

break;

case '+':

/* += */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_ASPLUS;

/* ++ */

else if (lexer_lookahead (cb, '+', 1))

_tokRec->type = TOK_INCR;

/* + */

else

_tokRec->type = TOK_PLUS;

break;

case '-':

/* -= */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_ASMINUS;

/* — */

else if (lexer_lookahead (cb, '-', 1))

_tokRec->type = TOK_DECR;

/* - */

else

_tokRec->type = TOK_MINUS;

break;

case '*':

/* *= */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_ASMUL;

/* * */

else

_tokRec->type = TOK_MUL;

break;

case '/':

/* /= */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_ASDIV;

/* / */

else

_tokRec->type = TOK_DIV;

break;

case '^':

/* ^ */

_tokRec->type = TOK_EXP;

break;

case '%':

/*%= (modulus) */

if (lexer_lookahead (cb, '=', 1))

_tokRec->type = TOK_ASMOD;

/*% */

else

_tokRec->type = TOK_MOD;

break;

}

/* Конец проверки. Это оператор? */

if (_tokRec->type ≠ TOK_EOF)

{

*(_tokRec->str) = ch;

*(_tokRec->str+1) = '';

goto l_end;

}

/* Конец ввода данных? */

if (ch == TOK_EOF)

{

_tokRec->type = ch;

goto l_end;

}

/* Новая строка или новый оператор? */

if (ch == ';' || ch == 'n')

{

_tokRec->type = ch;

*(_tokRec->str) = ch;

goto l_end;

}

if (strchr («(),.{}», ch))

{

/* Знаки) (;., } { */

_tokRec->type = ch;

*(_tokRec->str) = ch;

goto l_end;

}

// Идентификатор

ch2 = tolower (ch);

if ((ch2 >= 'a' && ch2 <= 'z') || strchr («_$», ch))

{

*buf = ch;

cPtr = buf +1;

ch = lexer_get_char (cb);

while ((isalnum (ch) || strchr («_$», ch)) && ch ≠ TOK_EOF)

{

*cPtr++ = ch;

ch = lexer_get_char (cb);

}

*cPtr = '';

/* Возврат последнего символа в поток данных */

lexer_put_back (cb, ch);

_tokRec->type = TOK_IDENT;

int len = min (strlen (buf), MAX_TOKEN_LEN);

strncpy (_tokRec->str, buf, len);

*(_tokRec->str + len) = '';

}

/* Текстовая строка «xxx» или 'xxx' */

else if (ch == '" ' || ch == ''')

{

char chStart = ch;

cPtr = buf;

ch2 = ''; // Поддержка кавычек внутри текста «…» …"

while (1)

{

ch = lexer_get_char (cb);

if (ch == TOK_EOF) break;

// Проверка «и '

if (ch == chStart && ch2 ≠ '\')

{

break;

}

else

{

ch2 = *cPtr;

*cPtr++ = ch;

}

}

*cPtr = '';

int len = min (strlen (buf), MAX_TOKEN_LEN);

strncpy (_tokRec->str, buf, len);

*(_tokRec->str + len) = '';

_tokRec->type = TOK_STRING;

}

/* Это целое число или десятичное; 123, 0.51,.67, -2.67, +89, -4e3, +2e-9*/

else if (strchr («123 456 789±.», ch))

{

int hasDecimal = 0;

int hasExp = 0;

int hasExpSign = 0;

cPtr = buf;

*cPtr++ = ch;

if (ch == '.') { hasDecimal = 1; }

/* Принимаются следующие варианты записи:

.67, -2.67, +89, -4e3, +2e-9

*/

/* Также принимаются шестнадцатеричные числа в виде 0x7FCD и 0XA. */

int is_hex = FALSE;

if (ch == '0')

{

is_hex = lexer_lookahead (cb, 'x', 1/*Истина*/);

if (!is_hex)

is_hex = lexer_lookahead (cb, 'X', 1/*Истина*/);

}

/* Добавляем 'x' чтобы запись соответствовала формату «0x» */

if (is_hex)

*cPtr++ = 'x';

unsigned int count = 0;/*Сброс индекса*/

while (1)

{

ch = lexer_get_char (cb);

if (ch == TOK_EOF) break;

if (ch == '.' && !hasDecimal)

{

*cPtr++ = ch;

hasDecimal = 1;

}

else if ((ch == 'e' || ch == 'E') && !hasExp)

{

*cPtr++ = ch;

hasExp= 1;

}

else if (strchr («±», ch) && hasExp && (!hasExpSign))

{

*cPtr++ = ch;

hasExpSign = ch;

}

else if (strchr («123 456 789», ch))

{

*cPtr++ = ch;

}

else if (is_hex && strchr («ABCDEFabcdef», ch))

{

*cPtr++ = ch;

}

else

break;

if (count++ > MAX_TOKEN_LEN) break;

}

/* Возвращаем последний символ обратно в поток */

lexer_put_back (cb, ch);

*cPtr = '';

double d = atof (buf);

_tokRec->type = TOK_NUMERIC;

/* Возвращаем число в виде строки */

int len = min (strlen (buf), MAX_TOKEN_LEN);

strncpy (_tokRec->str, buf, len);

*(_tokRec->str + len) = '';

if (hasDecimal || hasExpSign == (int)'-')

{

_tokRec->val.d = d;

}

else

{

/* На самом деле целое */

_tokRec->val.d = (long)d;

}

} /* Конец проверки на число */

else

{

/* Неизвестный символ. Прекращаем дальнейший ввод */

_tokRec->type = TOK_EOF;

}

l_end:

/* Заносим номер строки и возвращаем token (*_tokRec) и его тип */

_tokRec->line_num = lexer_line_num (cb);

return _tokRec->type;

}

int lexer_line_num (CodeBuffer *cb)

{

return cb->line_num;

}

void lexer_put_back (CodeBuffer *cb, char _ch)

{

size_t len = strlen (cb->char_backbuf);

if (len < MAX_CHAR_BACKBUF_LEN — 1)

{

*(cb->char_backbuf + len) = _ch;

*(cb->char_backbuf + len+1) = '';

}

else

{

lexer_error (cb, «Буфер Parser’а переполнен.»);

}

}

void lexer_remove_line (CodeBuffer *cb)

{

int ch = lexer_get_char (cb);

while (ch ≠ TOK_EOF && ch ≠ 'n')

{

ch = lexer_get_char (cb);

}

lexer_put_back (cb, ch);

}

int lexer_get_charEx (CodeBuffer *cb)

{

int ch;

int ch2;

int move;

ch = lexer_get_char (cb);

while (ch ≠ TOK_EOF)

{

move = 0;

/* Удаляем пробелы */

while (isspace (ch))

{

ch = lexer_get_char (cb);

}

/* Удаляем строки начинающиеся с '#' */

if (ch == '#')

{

lexer_remove_line (cb);

ch = lexer_get_char (cb);

}

/* Конец строки (оператора)? */

if (ch == 'n' || ch == ';')

{

return ch;

}

/* Удаляем пробелы */

while (isspace (ch))

{

ch = lexer_get_char (cb);

}

/* Удаляем комментарии которые начинаются с '/ *' и заканчиваются */

if (ch == '/')

{

ch2 = lexer_get_char (cb);

if (ch2 == '/')

{

/* Чтение до конца строки */

ch = lexer_get_char (cb);

while (ch ≠ TOK_EOF && ch ≠ 'n')

{

ch = lexer_get_char (cb);

}

move = 1;

}

else if (ch2 == '*')

{

int count = 1; // Внутренний счетчик /* /* /*… */ */ */

ch = lexer_get_char (cb);

ch2 = 0;

while (ch ≠ TOK_EOF)

{

// Комментарий закончился символом '*/'

if (ch == '/' && ch2 == '*')

{

if (—count <= 0)

{

move = 1;

break;

}

}

// Пропускаем все что внутри комментария /*

else if (ch == '*' && ch2 == '/')

{

count++;

}

else if (ch == 'n'|| ch == 'r')

{

;

}

/* Предыдущий символ */

ch2 = ch;

ch = lexer_get_char (cb);

}

if (ch == TOK_EOF && count)

{

lexer_error (cb, «Многострочный комментарий не закрыт /*… */ «);

}

}

else

{

lexer_put_back (cb, ch2);

}

}

if (move)

ch = lexer_get_char (cb);

else

break;

}

return ch;

}

int lexer_lookahead (CodeBuffer *cb, int _match_ch, int _remove)

{

int ret;

int ch = lexer_get_charEx (cb);

if (ch == _match_ch)

{

if (!_remove) lexer_put_back (cb, ch);

ret = 1;

}

else

{

lexer_put_back (cb, ch);

ret = 0;

}

return ret;

}

int lexer_get_char (CodeBuffer *cb)

{

int ch = TOK_EOF;

/* Проверяем содержимое буфера */

if (cb->char_backbuf[0] ≠ '')

{

size_t len = strlen (cb->char_backbuf);

ch = *(cb->char_backbuf + len — 1);

*(cb->char_backbuf + len-1) = '';

return ch;

}

if (!cb->text)

return TOK_EOF;

else if (*(cb->text + cb->curr_pos) == TOK_EOF)

{

return TOK_EOF;

}

ch = *(cb->text + cb->curr_pos);

if (ch == 'n')

cb->line_num++;

cb->curr_pos++;

return ch;

}

void lexer_error (CodeBuffer *cb, char *_msg)

{

fprintf (stderr, «Лексическая ошибка:%s.%sn», (cb->name? cb->name: «»), _msg);

}

int lexer_match (char *tok1, char *tok2)

{

if (!(tok1 && tok2)) return FALSE;

size_t len1 = strlen (tok1);

size_t len2 = strlen (tok2);

if (len2 < len1)

/* Соответствие шаблона в части tokenа, например lexer_match («abcd», «ab») => TRUE */

return !strncmp (tok1, tok2, len2);

else

/* Длинна Tokenа и шаблона должны совпадать */

return !strcmp (tok1, tok2);

}

CodeBuffer *lexer_codebuffer_new (char *code)

{

CodeBuffer *cb = (CodeBuffer *)calloc (1, sizeof (CodeBuffer));

lexer_codebuffer_init (cb);

/* Выделить память для кода */

size_t len = min (strlen (code), 40 960);

if (len)

{

cb->text =(char*) calloc (len+1, sizeof (char));

strncpy (cb->text, code, len);

}

return cb;

}

void lexer_codebuffer_init (CodeBuffer *cb)

{

cb->text = cb->name = NULL;

cb->curr_pos = 0;

cb->line_num = 1;

memset (cb->char_backbuf, '', MAX_CHAR_BACKBUF_LEN);

/* Счетчик Tokenов */

cb->tok_backbuf_count = 0;

/* Выделить память под переменные (MAX_VARIABLE_LIST_LEN) */

cb->variable_list = parser_variable_create_list ();

}

void lexer_codebuffer_destroy (CodeBuffer *cb)

{

if (!cb) return;

/* Очистить буфер кода */

free (cb->text);

free (cb->name);

cb->curr_pos = 0;

cb->line_num = 1;

/* Удалить все переменные */

parser_variable_delete_all (cb->variable_list);

cb->variable_list = NULL;

memset (cb->char_backbuf, '', MAX_CHAR_BACKBUF_LEN);

/* Обнулить счетчик Tokenов */

cb->tok_backbuf_count = 0;

}

4. Описание тестового примера

Текст программы:

a=sqrt (36)

b=abs (-6)

c=22

d=exp (30)

e=ln (10)

print (a)

print (b)

print (c)

print (d)

print (e)

f=3.4+2.6

print (f)

g=a+b*c-d/e*f

print (g)

Результат

Результат:6

Результат:6

Результат:4

Результат:1.06865e+13

Результат:2.30 259

Результат:6

Результат:-2.78465e+13

Заключение

В данной курсовой работе была выполнена задача создания простой программы-интерпретатора для обработки исходных текстов программ, выполняющих действия над комплексными числами.

Библиографический список

1. Серебряков В. А., Галочкин М. П., Гончар Д. Р., Фуругян М. Г. Теория и реализация языков программирования. М.: «МЗ-Пресс», 2003. 296 с.

2. Атакищев О. И., Волков А. П., Титов В. С., Старков Ф. А. Формальные грамматики и их применение в распознавании образов. — Курск, 2000. -115с.

3. Бек Л.

Введение

в системное программирование. — М.: Мир, 1988. — 448 с.

4. Молчанов А. Ю. Системное программное обеспечение — СПб.: Питер, 2003 г.

Показать весь текст
Заполнить форму текущей работой