kursovik / прогам реализация
.docx2.1 Программная реализация интерпретатора модифицированного языка MILAN (с комментариями).
<?php
//Описание классов
/* элемент массива лексем */
class Element_Lexems
{
/* код лексемы */
public $Code = 0 ;
/* значение лексемы */
public $Value = 0 ;
}
/* Элемент таблицы ключевых [зарезервированных] слов */
class Element_Key_Words
{
/* Ключевое слово */
public $Key_Word = '';
/* Код ключевого слова */
public $Code_Key_Word = 0;
}
//Описание констант
/* Количество ключевых слов языка МИЛАН */
define("MAX_KEY_WORDS",18);
/* Кода ключевых слов языка МИЛАН */
define("_BEGIN_", 1);
define("_DO_", 2);
define("_ELSE_", 3);
define("_END_", 4);
define("_ENDDO_", 5);
define("_ENDIF_", 6);
define("_IF_", 7);
define("_OUTPUT_", 8);
define("_READ_", 9);
define("_THEN_", 10);
define("_WHILE_", 11);
define("_SWITH_", 21);
define("_CASE_", 22);
define("_DEFAUT_", 23);
define("_FOR_", 24);
define("_TO_", 25);
define("_STEP_", 26);
define("_ENDFOR_", 27);
/* Кода лексем языка МИЛАН */
define("_SEMICOLON_",12); /* ; */
define("_RELATION_",13); // операция типа отношение
/* значения операции типа отношение */
define("_EQUAL_", 0); /* = */
define("_NOTEQUAL_", 1); /* <> */
define("_GT_", 2); /* > */
define("_LT_", 3); /* < */
define("_GE_", 4); /* >= */
define("_LE_", 5); /* <= */
define("_SUMM_", 14); /* операция типа сложение */
/* значения операции типа сложение */
define("_PLUS_", 0); /* + */
define("_MINUS_", 1); /* - */
define("_MUL_", 15); /* операция типа умножение */
/* значения операции типа сложение */
define("_STAR_", 0); /* * */
define("_SLASH_", 1); /* / */
define("_ASSIGNMENT_", 16); /* присваивание */
define("_INC_", 28);
define("_COLON_", 31); /* : */
define("_BRACE_OPEN_", 29); /* { */
define("_BRACE_CLOSE_", 30); /* } */
define("_LPAREN_", 17); /* ( */
define("_RPAREN_", 18); /* ) */
define("_IDENTIFIER_", 19); /* идентификатор */
define("_CONSTANT_", 20); /* константа */
define("_COM_", 21); /* // */
/* Таблица ключевых [зарезервированных] слов языка МИЛАН */
/* Ключевые слова в массиве должны быть упорядочены, т.к. */
/* поиск в массиве осуществляется методом "бинарного поиска" */
$Table_Key_Words = Array();
function ct_AddElement($Key_Word, $Code_Key_Word)
{
$ct_Element = new Element_Key_Words;
$ct_Element->Key_Word = $Key_Word;
$ct_Element->Code_Key_Word = $Code_Key_Word;
return $ct_Element;
}
//создаём новый массив
$Table_Key_Words[1] = ct_AddElement('BEGIN', _BEGIN_);
$Table_Key_Words[2] = ct_AddElement('CASE', _CASE_);
$Table_Key_Words[3] = ct_AddElement('DEFAUT', _DEFAUT_);
$Table_Key_Words[4] = ct_AddElement('DO', _DO_);
$Table_Key_Words[5] = ct_AddElement('ELSE', _ELSE_);
$Table_Key_Words[6] = ct_AddElement('END', _END_);
$Table_Key_Words[7] = ct_AddElement('ENDDO', _ENDDO_);
$Table_Key_Words[8] = ct_AddElement('ENDFOR', _ENDFOR_);
$Table_Key_Words[9] = ct_AddElement('ENDIF', _ENDIF_);
$Table_Key_Words[10] = ct_AddElement('FOR', _FOR_);
$Table_Key_Words[11] = ct_AddElement('IF', _IF_);
$Table_Key_Words[12] = ct_AddElement('OUTPUT', _OUTPUT_);
$Table_Key_Words[13] = ct_AddElement('READ', _READ_);
$Table_Key_Words[14] = ct_AddElement('STEP', _STEP_);
$Table_Key_Words[15] = ct_AddElement('SWITH', _SWITH_);
$Table_Key_Words[16]= ct_AddElement('THEN', _THEN_);
$Table_Key_Words[17] = ct_AddElement('TO', _TO_);
$Table_Key_Words[18]= ct_AddElement('WHILE', _WHILE_);
/* максимально допустимое количество идентификаторов в программе */
define("MAX_IDENTIFIERS", 15);
/* максимально допустимое количество констант в программе */
define("MAX_CONSTANTS", 15);
/* максимально допустимое количество лексем в программе */
define("MAX_LEXEMS", 500);
/* массив сообщений об ошибках в программе на МИЛАНе */
$Error_Message = Array(
/* 1 */ 'Неизвестный символ в программе.',
/* 2 */ 'Превышение максимального количества идентификаторов.',
/* 3 */ 'Превышение максимального количества констант.',
/* 4 */ 'Переполнение массива лексем.',
/* 5 */ 'Переполнение стека Stek_do.',
/* 6 */ 'Нехватка элементов в стеке Stek_do.',
/* 7 */ 'Неправильное обращение к функции для работы со стеком Stek_do.',
/* 8 */ 'Переполнение стека Stek_if.',
/* 9 */ 'Нехватка элементов в стеке Stek_if.',
/* 10 */ 'Неправильное обращение к функции для работы со стеком Stek_if.',
/* 11 */ 'Несоответствие в операторах WHILE-DO-ENDDO.',
/* 12 */ 'Несоответствие в операторах IF-THEN-ELSE-ENDIF.',
/* 13 */ 'Конструкция <программа>. Нет BEGIN.',
/* 14 */ 'Конструкция <программа>. Нет END.',
/* 15 */ 'Переполнение стека StekIdent.',
/* 16 */ 'Конструкция <оператор>. Неверное присваивание.',
/* 17 */ 'Нехватка элементов в стеке StekRes.',
/* 18 */ 'Нехватка элементов в стеке StekIdent.',
/* 19 */ 'Конструкция <оператор>. Неверный оператор OUTPUT.',
/* 20 */ 'Конструкция <оператор>. Неверный оператор WHILE.',
/* 21 */ 'Конструкция <оператор>. Отсутствует THEN в операторе IF.',
/* 22 */ 'Конструкция <оператор>. Отсутствует ENDIF в операторе IF.',
/* 23 */ 'Конструкция <оператор>. Отсутствует ELSE или ENDIF в операторе IF.',
/* 24 */ 'Конструкция <условие>. Неверная операция отношения.',
/* 25 */ 'Переполнение стека StekRel.',
/* 26 */ 'Нехватка элементов в стеке StekRel.',
/* 27 */ 'Переполнение стека StekRes.',
/* 28 */ 'Нехватка элементов в стеке StekMul.',
/* 29 */ 'Переполнение стека StekMul.',
/* 30 */ 'Деление на ноль.',
/* 31 */ 'Конструкция <множитель>. Нет закрывающей скобки.',
/* 32 */ 'Переполнение стека StekSum.',
/* 33 */ 'Нехватка элементов в стеке StekSum.',
/* 33 */ 'Нехватка элементов в стеке StekSum.',
/* 34 */ 'Конструкция <оператор>. Отсутствует ( в операторе SWITH.',
/* 35 */ 'Конструкция <оператор>. Отсутствует ) в операторе SWITH.',
/* 36 */ 'Переполнение стека $StekCaseValue',
/* 37 */ 'Переполнение стека $StekDefaultValue',
/* 38 */ 'Конструкция <оператор>. Отсутствует { в операторе SWITH.',
/* 39 */ 'Конструкция <оператор>. Отсутствует CASE в операторе SWITH.',
/* 40 */ 'Нехватка элементов в стеке $StekCaseValue',
/* 41 */ 'Конструкция <оператор>. Отсутствует константа в операторе SWITH.',
/* 42 */ 'Нехватка элементов в стеке $StekDefaultValue',
/* 43 */ 'Конструкция <оператор>. Отсутствует : в операторе SWITH.',
/* 44 */ 'Конструкция <оператор>. Отсутствует } в операторе SWITH.',
/* 45 */ 'Перепонение стека $Stek_case.',
/* 46 */ 'Нехватка элементов в стеке $Stek_case.',
/* 47 */ 'Несоответствие в операторах SWITH-CASE-DEFAUT',
/* 48 */ 'Конструкция <оператор>. Отсутствует идентификатор в операторе FOR.',
/* 49 */ 'Конструкция <оператор>. Отсутствует присвоение в операторе FOR.',
/* 50 */ 'Конструкция <оператор>. Отсутствует TO в операторе FOR.',
/* 51 */ 'Конструкция <оператор>. Отсутствует ENDFOR в операторе FOR.',
/* 52 */ 'Переполнение стека $StekForExit',
/* 53 */ 'Нехватка элементов в стеке $StekForExit',
/* 54 */ 'Несоответствие в операторах FOR-TO-ENDFOR',
/* 55 */ 'Переполнение стека $Stek_to',
/* 56 */ 'Нехватка элементов в стеке $Stek_to');
/* массив лексем */
$Tab_Lexems = Array ();
/* массив идентификаторов */
$Tab_Identifiers = Array ();
/* массив констант */
$Tab_Constants = Array ();
/* Имя программы на языке МИЛАН */
$Input_Programm = '';
/* Входной файл программы на языке МИЛАН */
/* Входной символ программы на языке МИЛАН */
$Input_Letter = '';
/* Номер очередного символа в программе */
$Number_Letter = 0;
/* Код ошибки */
$Code_Error = -1 ;
/* Номер строки и позиции в которой ошибка */
$Number_String = 0;
$Position = 0;
/* Номер очередной лексемы в программе */
$Number_Lexem = 0;
/* Сформированная Лексическим Анализатором лексема */
$Current_Lexem = new Element_Lexems;
/* Количество лексем в программе */
$Number_Lexems_Programm = 0;
/* Номер очередного идентификатора в программе */
$Number_Identifiers = 0;
/* Номер очередной константы в программе */
$Number_Constants = 0;
/*************************************************************************/
/* Stek_Integer(...) */
/* Функция для работы со стеками типа Integer. */
/* Аргументы: */
/* Operation - код операции ( 0 - инициализация стека; */
/* 1 - извлечение элемента из стека */
/* в Element; */
/* 2 - добавление элемента */
/* в стек Element; */
/* $Current_Stek - массив из 50 элементов ; */
/* $Top - вершина стека ; */
/* $Element - элемент который кладется в стек или в который */
/* возвращается вершина стека. */
/* Функция возвращает значение TRUE, если операция работы со стеком */
/* выполнена успешно, FALSE - в противном случае. */
/*************************************************************************/
function Stek_Integer( $Operation ,
&$Current_Stek,
&$Top,
&$Element)
{
global $Code_Error;
switch ($Operation):
/* Инициализация стека */
Case 0 :
$Top=0;
for ($i=1;$i<=50;$i++)
{
$Current_Stek[$i]=0;
}
break;
/* Извлечение элемента со стека */
Case 1 :
if ($Top<=0)
{
return FALSE;
}
else
{
$Element=$Current_Stek[$Top];
$Top--;
}
break;
/* Добавление элемента в стек */
Case 2 :
if ($Top>=50)
{
return FALSE;
}
else
{
$Top++;
$Current_Stek[$Top]=$Element;
}
break;
/* Сообщение об ошибке */
default:
$Code_Error=4;
return FALSE;
endswitch;
return TRUE;
} /* End Stek_Integer*/
/*************************************************************************/
/* Replicate(<ВырC>,<ВырN>) */
/* Аргументы: <ВырC>, <ВырN>. */
/* Результат: Функция возвращает символьную строку, полученную */
/* повторением <ВырN> раз строки <ВырC>. */
/*************************************************************************/
Function Replicate($String_Letter, $Num)
{
$Word='';
for($i=1; $i<=$Num; $i++)
$Word = $Word . $String_Letter;
return $Word;
} /* End Replicate */
/*************************************************************************/
/* Space(<ВырN>) */
/* Аргументы: <ВырN>. */
/* Функция возвращает строку, состоящую из <ВырN> пробелов. */
/*************************************************************************/
Function Space($Num)
{
return Replicate(' ',$Num);
} /* End Space */
/*************************************************************************/
/* Print_Error */
/* Процедура вывода на экран сообщения об ошибке для */
/* Лексического Анализатора */
/* Расстановки ссылок */
/* Интерпретатора */
/*************************************************************************/
function Print_Error($Variant)
{
global $Number_String;
global $Position;
global $Number_Lexem;
global $Code_Error;
global $Error_Message;
global $Tab_Lexems;
global $ct_buf;
switch ($Variant)
{
Case 1 :
print ('<html><head><title>РЕЗУЛЬТАТ РАБОТЫ ЛЕКСИЧЕСКОГО АНАЛИЗАТОРА</title></head><body><br><H2 align="center">РЕЗУЛЬТАТ РАБОТЫ ЛЕКСИЧЕСКОГО АНАЛИЗАТОРА</H2><br><hr><br>
<table cellspacing="3" cellpadding="3" align="center"><tr><td >НАЙДЕНА ОШИБКА: </td><td align="center"><font color="red"> ' . $Error_Message[$Code_Error] . '</font></td></tr>
<tr><td> СТРОКА: </td><td align="left"><font color="blue">' . $Number_String . '</font></td></tr>
<tr><td> ПОЗИЦИЯ:</td><td align="left"><font color="blue">' . $Position . '</font></td></tr></table>
<br><hr><br><div align="center">
<form method="post" action="INTERFACE.php">
<input type="submit" value=" ОК " >
<input name="source" type="hidden" value="'.$ct_buf.'">
</form></div></body></html> ');
break;
Case 2 :
print ('<html><head><title>РЕЗУЛЬТАТ РАБОТЫ СИНТАКСИЧЕСКОГО АНАЛИЗАТОРА</title></head><body><br><H2 align="center">РЕЗУЛЬТАТ РАБОТЫ СИНТАКСИЧЕСКОГО АНАЛИЗАТОРА</H2><br><hr><br>
<table cellspacing="3" cellpadding="3" align="center"><tr><td >НАЙДЕНА ОШИБКА: </td><td align="center"><font color="red"> ' . $Error_Message[$Code_Error] . '</font></td></tr>
<tr><td> ЛЕКСЕМА: </td><td align="left"><font color="blue">' . $Number_Lexem . '</font></td></tr></table>
<br><hr><br><div align="center">
<form method="post" action="INTERFACE.php">
<input type="submit" value=" ОК ">
<input name="source" type="hidden" value="'.$ct_buf.'">
</form></div></body></html> ');
break;
}
} /* End Print_Error */
/************************************************************************/
/* Isdigit(<ВырC>) */
/* Функция возвращает значение TRUE, если <вырC> начинается с цифры. */
/************************************************************************/
Function Isdigit($Figure)
{
$ct_res=ereg("[0-9]", $Figure{0});
return $ct_res;
} /* End Isdigit */
/************************************************************************/
/* Isalpha(<ВырC>) */
/* Функция возвращает значение TRUE, если <вырC> начинается с буквы. */
/************************************************************************/
Function Isalpha($Letter)
{
$ct_res=ereg("[A-Za-zА-Яа-я]", $Letter{0});
return $ct_res;
} /* End Isalpha */
/*************************************************************************/
/* Lexical_Analyzer */
/* Лексический анализатор: Выполняет первую стадию транслятора - */
/* лексический анализ. Осуществляет просмотр исходного текста */
/* программы на МИЛАНе, распознавание и классификацию лексем. */
/* Строит: */
/* массив лексем; */
/* массив идентификаторов; */
/* массив констант; */
/* Производит расстановку ссылок для передачи управления. */
/* Входные данные: текст с программой на МИЛАНе. */
/* Результат: массив лексем, массив идентификаторов и констант. */
/*************************************************************************/
function Lexical_Analyzer()
{
/************************************************************************/
/* Found_in_Table_Key_Words */
/* Функция бинарного поиска в таблице ключевых слов */
/* Вход: Word - выражение символьного типа, Code - код найденного */
/* ключевого слова */
/* Выход: Функция возвращает значение TRUE, если Word ключевое слово, и */
/* FALSE - в противном случае. В переменной Code содержится код */
/* ключевого слова, или 0 в противном случае. */
/************************************************************************/
Function Found_in_Table_Key_Words($Word, &$Code)
{
global $Table_Key_Words;
$k=0;
$m=1;
$n=MAX_KEY_WORDS;
while ($m<=$n):
$k=intval($m+($n-$m) / 2);
if ($Word==$Table_Key_Words[$k]->Key_Word)
{
$Code=$Table_Key_Words[$k]->Code_Key_Word;
return TRUE;
}
elseif ($Word>$Table_Key_Words[$k]->Key_Word)
{
$m=$k+1;
}
else
$n=$k-1;
endwhile;
return FALSE;
}
/***********************************************************************/
/* Found_in_Table_Identifiers(<ВырC>) */
/* Функция для проверки идентификатора в таблице идентификаторов. */
/* Аргументы: <вырC>, содержащее имя идентификатора. */
/* Результат: номер идентификатора в таблице идентификаторов */
/* ( 0 - если идентификатор <ВырC> отсутствует в */
/* таблице идентификаторов). */
/***********************************************************************/
Function Found_in_Table_Identifiers($Identifier)
{
global $Tab_Identifiers;
global $Number_Identifiers;
for( $i=1;$i<=$Number_Identifiers;$i++)
{
if ($Tab_Identifiers[$i]==$Identifier)
return $i;
}
return 0;
} /* End Found_in_Table_Identifiers */
/*Функция Вывода сообщения об ошибке */
function Print_Error_Message()
{
global $Code_Error;
if ($Code_Error>-1)
{
Print_Error(1);
return 0;
}
//Если ошибок нет, то нормальное завершение лексического анализа
End_Lexical_Analyzer();
}
//Функция выхода из Лексического Анализатора
function End_Lexical_Analyzer()
{
global $Number_Lexems_Programm;
global $Number_Lexem;
global $Code_Error;
$Number_Lexems_Programm=$Number_Lexem;
/* Расстановка ссылок для операторов цикла и развилки */
Setup_Refference();
/* Проверка на ошибки, появившиеся в процессе расстановки ссылок */
if ($Code_Error>-1)
{
Print_Error(2);
return 0;
}
/* Печать таблицы массива лексем */
global $ct_milanMode;
global $ct_buf;
if($ct_milanMode==0)
{
Print_Tab_Lexems();
/* Печать таблицы массивов идентификаторов и констант */
Print_Tab_Identifiers_Constants();
/* Закрытие файла с программой на языке МИЛАН */
/* функция y10: нормальное завершение работы лексического анализатора */
global $Tab_Identifiers;
global $Tab_Constants;
global $ct_TabLEX_Value_str;
global $ct_TabLEX_Code_str;
//поля типа hidden используются для сохранения данных полученных в результате работы лексического анализатора $Tab_Constants, $Tab_Identifiers
print (
"<br><hr><br><div align=\"center\"><font color=\"blue\"> НОРМАЛЬНОЕ ЗАВЕРШЕНИЕ РАБОТЫ ЛЕКСИЧЕСКОГО АНАЛИЗАТОРА</font><br><br>
<form id=\"sourceform\" name=\"sourceform\" action='MILAN.PHP' method=\"post\" >
<input name=\"source\" type=\"hidden\" value='".$ct_buf."'> <!--поле хранит исходный код программы -->
<input name=\"lex_code\" type=\"hidden\" value='".$ct_TabLEX_Code_str."'> <!--поле хранит значения CODE таблицы лексем -->
<input name=\"lex_value\" type=\"hidden\" value='".$ct_TabLEX_Value_str."'> <!--поле хранит значения VALUE таблицы лексем -->
<input name=\"tab_ident\" type=\"hidden\" value='" .join('%',$Tab_Identifiers). "'> <!--поле хранит данные таблицы идентификаторов -->
<input name=\"tab_const\" type=\"hidden\" value='" .join('%',$Tab_Constants). "'> <!--поле хранит данные таблицы констант -->
<input name=\"next\" type=\"submit\" value=\"Далее\" align=\"center\" size=\"40\">
<input name=\"mode\" type=\"hidden\" value=\"1\"> <!--поле хранит текущий режим работы скрипта -->
</form></div> "
);
}
return 0;
}
/************************************************************************/
/* Letter; */
/* Процедура для выделения символов ключевого слова или */
/* идентификатора. Занесение в массив лексем кода и значения */
/* лексемы (ключевого слова или идентификатора). */
/* Аргументы: нет аргументов. */
/* Результат: нет результата. */
/************************************************************************/
Function Letter()
{
global $Input_Letter;
global $Current_Lexem;
global $Number_Identifiers;
global $Position;
global $Code_Error;
global $Tab_Identifiers;
/* Начало процедуры Letter */
$Word = '';
$Code_Word = 0;
$Position_ = 0;
/* функция у4: накопление символов ключевого слова или идентификатора */
$Word = $Word . $Input_Letter;
/* функция у1: прочитать следующий символ */
Read($Input_Letter);
$Position_++;
/* Выделить ключевое слово или идентификатор */
while ((Isalpha($Input_Letter)) || (Isdigit($Input_Letter))):
/* функция у4: накопление символов ключевого слова или идентификатора */
$Word=$Word . $Input_Letter;
/* функция у1: прочитать следующий символ */
Read($Input_Letter);
$Position_++;
endwhile;
/* функция у5: проверка на принадлежность */
/* выделенного слова к ключевым словам */
if (Found_in_Table_Key_Words($Word, $Code_Word))
{
/* функция у11: формирование лексемы */
$Current_Lexem->Code = $Code_Word;
$Current_Lexem->Value = 0;
}
/* функция у6: проверка на принадлежность */
/* выделенного слова к идентификаторам */
elseif (Found_in_Table_Identifiers($Word)>0)
{
/* функция у11: формирование лексемы */
$Current_Lexem->Code = 19;
$Current_Lexem->Value = Found_in_Table_Identifiers($Word);
}
elseif ($Number_Identifiers<MAX_IDENTIFIERS)
{
/* запись выделенного слова в таблицу идентификаторов */
$Number_Identifiers++;
$Tab_Identifiers[$Number_Identifiers]=$Word;
/* функция у11: формирование лексемы */
$Current_Lexem->Code=19;
$Current_Lexem->Value=$Number_Identifiers;
}
else
/* Превышение максимального количества идентификаторов */
$Code_Error=1;
if ($Code_Error==-1)
$Position+=$Position_;
} /* End Letter */
/***********************************************************************/
/* Found_in_Table_Constants(<ВырC>) */
/* Функция для проверки константы в таблице констант. */
/* Аргументы: <вырC>, содержащее константу. */
/* Результат: номер константы в таблице констант */
/* ( 0 - если константа <ВырC> отсутствует в таблице */
/* констант). */
/***********************************************************************/
Function Found_in_Table_Constants($Constant)
{
//глобальные переменные
global $Number_Constants;
global $Constant_Value;
global $Tab_Constants;
for($i=1;$i<= $Number_Constants;$i++)
{
$Constant_Value=intval($Constant);
if ($Tab_Constants[$i]==$Constant_Value)
return $i;
}
return 0;
} /* End Found_in_Table_Constants */
/************************************************************************/
/* Digit; */
/* Процедура для выделения символов константы, проверки в таблице */
/* констант и занесения в таблицу. */
/* Аргументы: нет аргументов. */
/* Результат: нет результата. */
/************************************************************************/
Function Digit()
{
/* Начало процедуры Digit */
//глобальные переменные
global $Current_Lexem;
global $Code_Error;
global $Tab_Constants;
global $Input_Letter;
global $Number_Constants;
//локальные переменные
$Constant_Value = 0;
$Word = '';
/* функция у7: накопление символов константы */
$Word = $Word . $Input_Letter;
$Position_=0;
/* функция у1: прочитать следующий символ */
Read($Input_Letter);
$Position_++;
/* Выделить константу */
while (Isdigit($Input_Letter)):
/* функция у7: накопление символов константы */
$Word=$Word . $Input_Letter;
/* функция у1: прочитать следующий символ */
Read($Input_Letter);
$Position_++;
endwhile;
/* функция у8: проверка на принадлежность */
/* выделенной константы таблице констант */
if (Found_in_Table_Constants($Word)>0)
{
/* функция у11: формирование лексемы */
$Current_Lexem->Code=20;
$Current_Lexem->Value=Found_in_Table_Constants($Word);
}
elseif ($Number_Constants<MAX_CONSTANTS)
{
/* запись выделенной константы в таблицу констант */
$Number_Constants++;
$Constant_Value=intval($Word);
$Tab_Constants[$Number_Constants]=$Constant_Value;