Skip to content

Instantly share code, notes, and snippets.

@MisterTimur
Last active January 13, 2023 11:56
Show Gist options
  • Save MisterTimur/86b2810a6d9942d8d869967b978ae727 to your computer and use it in GitHub Desktop.
Save MisterTimur/86b2810a6d9942d8d869967b978ae727 to your computer and use it in GitHub Desktop.
Интерпретатор на C++
// ConsoleApplication39.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
// Абдулов Тимур
#include "pch.h"
#include <iostream>
#include <string>
const char TI_SLO=1;// тип Слово
const char TI_CIF=2;// тип Число
const char TI_ZNA=3;// тип Занк
using namespace std;
typedef string STR;
typedef char CHA;
typedef bool BOL;
#pragma region ======================== Tr_Is_Float
// ゆうきイセル
// Функция определяет являеться ли строка числом
bool Tr_Is_Float(STR iStr){
bool p=0; // Количество точек
bool r=1; // Результат проверки по умолчанию true
int i=0; // Для цикла перебора символов
if(iStr[i]=='-') i++; // если минус то прпускаем
if(iStr[i]=='.') {i++;p++;} // если точка то пропускаем
for(;iStr[i]!='\0';i++){ // Перебираем знаки в строке
if(iStr[i]=='.'){// Если встретилась точка смотрим сколько их
if (p) r=0;// Если точек больше true то есть 1 то нечисло
else p++;// Увеличиваем количество точек с false на true
continue;}// Продолжаем работу цикла тут можно потсавить else
if(iStr[i]<'0'||iStr[i]>'9')r=0;// Если это не число то результат равен false
}// ПОсле выхода из цикла i всегда больше 0
if(iStr[i-1]<'0'||iStr[i-1]>'9')r=0;// Первый символ дожен быть числом
return r;// Вернуть результат прверки строки
}
#pragma endregion
#pragma region ====================== Tr_StrToFloat
float Tr_StrToFloat(STR iStr){ // Переводит строку в float с проверкой
float res=0;// В случае ошибки вернет 0
if (Tr_Is_Float(iStr)) // ПРоерка если в строке число то
res=strtof(&iStr[0],NULL);// Перевести в Float
return res;// Возращает результат
}
float F(char* iStr){return Tr_StrToFloat(iStr);}
#pragma endregion
bool EtoBuk(char iCha) { // ОРпределяет буквали это ?
bool Rez=false;
if (iCha>='a' && iCha<='z') Rez=true; else
if (iCha>='A' && iCha<='Z') Rez=true; else
if (iCha=='_' ) Rez=true;
return Rez;
}
bool EtoCif(char iCha) { // ОРпределяет цифра ли это ?
bool Rez=false;
if (iCha>='0' && iCha<='9') Rez=true;
return Rez;
}
bool EtoCifBuk(char iCha) { // Если это Буква или цифра то true
return ( EtoBuk(iCha) || EtoCif(iCha) );
}
string ReadSlovo(string &iStr,int &iPos,int &iLen) { // Читаем слово из строки
string Rez="";// Если не удалось прочитать слово вернет пустую строку
if (EtoBuk(iStr[iPos])) // Если это буква Слово может начинаться с буквы
while ((iPos<iLen) && (EtoCifBuk(iStr[iPos]))) // Содержит буквы или цифры
{ Rez=Rez+iStr[iPos]; iPos=iPos+1; } // Складываем слово и увеличиваем iPos
return Rez;// Возвращаем рузельтат
}
string ReadChisl(string &iStr,int &iPos,int &iLen) { // Читаем число из строки
string Rez="";
if (EtoCif(iStr[iPos])) // Если это цифра
while ((iPos<iLen) && (EtoCif(iStr[iPos])))
Rez += iStr[iPos++];
return Rez;
}
string ReadZnak2(string &iStr,int &iPos,int &iLen) { // Читаем двоной знак
string Rez="";
if (iPos<iLen+1) {
string S;
S=S+iStr[iPos];
S=S+iStr[iPos+1];
if (
(S=="&&") ||
(S=="||") ||
(S==":=") ||
(S=="==") ||
(S=="!=") ||
(S=="<>") ||
(S==">=") ||
(S=="<=")
) {Rez=S;iPos=iPos+2;}
}
return Rez;
}
string ReadZnak1(string &iStr,int &iPos,int &iLen) { // Читаем занк одинарный
string Rez="";
if (iPos<iLen) {
string S;
S=S+iStr[iPos];
if (
(S=="&") ||
(S=="|") ||
(S=="{") ||
(S=="}") ||
(S=="(") ||
(S==")") ||
(S=="[") ||
(S=="]") ||
(S=="=") ||
(S=="+") ||
(S=="-") ||
(S=="*") ||
(S=="/") ||
(S=="<") ||
(S==">")
) {Rez=S;iPos=iPos+1;}
}
return Rez;
}
class TEl {
public:
STR TXT;// Тект Элемента
STR ZNA;// Сдержимое элемента занчение
BOL FUN;// Если это функция
CHA TIP;// Тип токена
TEl*ROD;// Ссылка на родительский элемент
TEl*PRE;// Предыдущие слово в списке
TEl*NEX;// Следующее слово в списке
TEl*FIR;// Первый элемент в вложеном списке
TEl*LAS;// Последний элемент в вложеном списке
TEl*ADD(TEl*iEl) {// Добавить элемент в список
TEl*Rez;
iEl->DEL();// ОТсоеденяем от предудущего списка
if (FIR==0) { // Если вложеных элементов нету
FIR=iEl; // указываю как перывй элемент вложеного списка
LAS=FIR;// Указываю что он же являеться последним
FIR->PRE=0;// Указываю что предыдущего элемента нету
FIR->NEX=0;// Указываю что следующего элемента нету
FIR->ROD=this;// Указываю родительский элемент
Rez=FIR;
}
else { // Если уже есть вложеные элементы то крепим к LST
LAS->NEX=iEl;// Доабвлю новый элемент в конец списка
LAS->NEX->PRE=LAS;// Указваем ссылку на предыдыщий элемент
LAS->NEX->ROD=this;// Указывем родительский элемент
LAS->NEX->NEX=0;// Указывем следующий элемент
LAS=LAS->NEX;// Указываем как новый послдений эдемент в списке
Rez=LAS;
}
return Rez;
}
TEl*DEL() { // Удаляет элемент из списка
if (ROD!=0) // Если удаляемый элемент являеться последним в списке
if (ROD->LAS==this) ROD->LAS=PRE;
if (ROD!=0) // Если удаляемый элемент являеться Первым в списке
if (ROD->FIR==this) ROD->FIR=NEX;
if (PRE!=0) PRE->NEX=NEX;// Отсоеденяем от предыдыщего
if (NEX!=0) NEX->PRE=PRE;// Отсоеденяем от следующего
NEX=0;
PRE=0;
ROD=0;
return this;
}
TEl*ADD(STR iStr,CHA iTip) {// Добавить слово в список
TEl*Rez=0;
if (iStr!="") {
Rez = new TEl();// Создаю новый элемент
Rez->TXT=iStr;// Указываю текс элемента
Rez->ZNA=iStr;// Указываю значение элемента
Rez->TIP=iTip;// Указываю тип эдемента
ADD(Rez);// Добавлю соданый элемент в вложенй список
}
return Rez;// Возвращаю ссылку на созданый эдемент
}
TEl*FIN(STR iStr) { // Ищим функцию с именем iStr
TEl*Rez=0 ;// Результат поиска фунции
if ((FUN) && (TXT==iStr)) Rez=this;
TEl*lEl=this;// Поиск начинаем с текущего элемента
lEl=lEl->PRE;// Переходим к предыдущему элементу
while ((lEl!=0)&&(Rez==0)) // Переббираем элементы
if ((lEl->FUN) && (lEl->TXT==iStr)) Rez=lEl;else
lEl=lEl->PRE;// Переходим к предыдущему элементу
// ПОиск переменной внутри параметров функции
if (Rez==0)
if (ROD!=0)
if (ROD->FUN)
if (ROD->FIR->TXT=="(")
if (ROD->FIR->FIR!=0) {
TEl*lEl=ROD->NEX->NEX;
while ((lEl!=0) && (Rez==0))
if (lEl->TXT==iStr) Rez=lEl;else lEl=lEl->NEX;
}
if ((Rez==0) && (ROD!=0)) Rez=ROD->FIN(iStr);
return Rez;
}
TEl*COP(TEl*IRod,TEl*IPre){// Возвращает копию Элемента
TEl*Rez=new TEl();
Rez->TXT=TXT;
Rez->ZNA=ZNA;
Rez->TIP=TIP;
Rez->FUN=FUN;
Rez->ROD=IRod;
Rez->PRE=IPre;
Rez->NEX=0;
Rez->FIR=0;
if (FIR!=0) {
Rez->FIR = FIR->COP(Rez,0);
TEl*Ne=FIR->NEX;
TEl*Pr=Rez->FIR;
while (Ne!=0) {
Pr->NEX=Ne->COP(Rez,Pr);
Ne=Ne->NEX;
Pr=Pr->NEX;
}
}
return Rez;
}
TEl() { // Конструктор на всякий пажарный случай
PRE=0;
NEX=0;
LAS=0;
FIR=0;
}
void CopPar(TEl*iEl1,TEl*iEl2) { // Копирование параметров функции
TEl*L1=iEl1;
TEl*L2=iEl2;
while ((L1!=0) && (L2!=0)) {
L1->ZNA=L2->ZNA;
L1=L1->NEX;
L2=L2->NEX;
};
}
void OP_SCO() { // Операция Скобка
if (FIR!=0){
Runs();// Вычислем содержимое скобки
ZNA=FIR->ZNA;
}
}
void OP_MUL() { // Операция умножения
if (FIR!=0) // ПРверяем есть ли первый элемент вложеного списка
if (FIR->NEX!=0) // ПРоверяем есть ли второй эдемент вложеного списка
{
FIR->Run();// Выполнить первый элемент
FIR->NEX->Run();// Выполнить второй элемент
if (Tr_Is_Float(FIR->ZNA)) // Если это число
if (Tr_Is_Float(FIR->NEX->ZNA)) // Если это число
ZNA=to_string(Tr_StrToFloat(FIR->ZNA)*Tr_StrToFloat(FIR->NEX->ZNA));
}
}
void OP_DIV() { // Операция деления
if (FIR!=0) // ПРверяем есть ли первый элемент вложеного списка
if (FIR->NEX!=0) // ПРоверяем есть ли второй эдемент вложеного списка
{
FIR->Run();// Выполнить первый элемент
FIR->NEX->Run();// Выполнить второй элемент
if (Tr_Is_Float(FIR->ZNA)) // Если это число
if (Tr_Is_Float(FIR->NEX->ZNA)) // Если это число
if (Tr_StrToFloat(FIR->NEX->ZNA)!=0) // Если второе занчение не ноль
ZNA=to_string(Tr_StrToFloat(FIR->ZNA)/Tr_StrToFloat(FIR->NEX->ZNA));
}
}
void OP_SUM() { // Операция сложения
if (FIR!=0) // ПРверяем есть ли первый элемент вложеного списка
if (FIR->NEX!=0) // ПРоверяем есть ли второй эдемент вложеного списка
{
FIR->Run();// Выполнить первый элемент
FIR->NEX->Run();// Выполнить второй элемент
if ((Tr_Is_Float(FIR->ZNA)) && (Tr_Is_Float(FIR->NEX->ZNA)))
ZNA=to_string(Tr_StrToFloat(FIR->ZNA)+Tr_StrToFloat(FIR->NEX->ZNA));
else
ZNA=FIR->ZNA+FIR->NEX->ZNA;
}
}
void OP_SUB() { // Операция вычитания
if (FIR!=0) // ПРверяем есть ли первый элемент вложеного списка
if (FIR->NEX!=0) // ПРоверяем есть ли второй эдемент вложеного списка
{
FIR->Run();// Выполнить первый элемент
FIR->NEX->Run();// Выполнить второй элемент
if ((Tr_Is_Float(FIR->ZNA)) && (Tr_Is_Float(FIR->NEX->ZNA)))
ZNA=to_string(Tr_StrToFloat(FIR->ZNA)-Tr_StrToFloat(FIR->NEX->ZNA));
}
}
void OP_LET() { // Операция присваивания
if ((FIR!=0)&&(FIR->NEX!=0)){
TEl*FU=FIN(FIR->TXT);
if (FU!=0){
FIR->NEX->Run();
FU->ZNA=FIR->NEX->ZNA;
}
}
}
void OP_PRI() { // Операция вывода в консоль
if (FIR!=0) // Если есть вложеныей элемент
if (FIR->TXT=="(") // Если вложеный элемент это скобка
{
FIR->Runs(); // Выполняю содержимое скобки
TEl*lEl=0; // ДЛя перебор элементов
if (FIR->FIR!=0) // Если в скобке есть что то
lEl=FIR->FIR; // Беру первый элемент в скобке
while (lEl!=0) { // Пока не дойду до кона списка
cout<<lEl->ZNA; // Вывожу в консоль
lEl=lEl->NEX; // Переходу к следующему элементу в скобке
}
}
}
void OP_FUN() { // Пытаемся выполнить как функцию
TEl*FN=FIN(TXT);// Ищим функцию ))))
if (FN!=0) {// Если такая функция найдена
TEl*RU=FN->COP(ROD,PRE);// Создаю копию функции
FIR->Run();// Вычисляю содержимое параметров если они есть
CopPar(FIR->FIR,RU->FIR->FIR);// Копирую параметры
RU->FIR->NEX->Run();// Запускаю функцию
ZNA=RU->ZNA;// Влзращаю результат
free(RU);// Освобождаю копию функции
}
}
void Run() { // Выполнить элемент
if (TXT=="(" ) OP_SCO();else // Операция Скобка
if (TXT=="*" ) OP_MUL();else // Операция умножения
if (TXT=="/" ) OP_DIV();else // Операция деления
if (TXT=="+" ) OP_SUM();else // Операция сложения
if (TXT=="-" ) OP_SUB();else // Операция вычитания
if (TXT==":=" ) OP_LET();else // Операция присваивания
if (TXT=="PRINT") OP_PRI();else // Операция Вывода в консоль
if (TXT=="{" ) Runs();else // Операция Скобка
if (TIP==TI_SLO ) OP_FUN(); // Пытаемся выполнить как функцию
}
void Runs() { // Выполнить элементы
TEl*lEl=FIR;// Перебираем элементы в списке
while (lEl!=0) { // Пока не дойдем до конца списка
if (!lEl->FUN) lEl->Run();// Выполнить элемент
lEl=lEl->NEX;// Передти к следующему
}
}
};
TEl* RedSlo(STR iStr) { // Создает список слов
int lPos=0;// Номер читаемого символа в строке
int lLen=iStr.length();// Это просто длина строки
TEl*REZ = new TEl();// Структура программы здесь храниться программ
while (lPos<lLen) // Создаем список слов в PRO
if (!REZ->ADD(ReadSlovo(iStr,lPos,lLen),TI_SLO))
if (!REZ->ADD(ReadChisl(iStr,lPos,lLen),TI_CIF))
if (!REZ->ADD(ReadZnak2(iStr,lPos,lLen),TI_ZNA))
if (!REZ->ADD(ReadZnak1(iStr,lPos,lLen),TI_ZNA)) lPos=lPos+1;
return REZ;
}
void Vlojit(TEl*iEl,char S1,char S2) { // Вложить скобки
TEl*lEl=iEl->FIR;// Перебираемые элементы текущий элемент
TEl*lSc=0 ;// Сюда складываем последующие элементы после скобки
TEl*MEl;
while (lEl!=0) {// ПОка не встретим конец списка
if (lEl->FIR!=0) Vlojit(lEl,S1,S2);
MEl=lEl->NEX;
if (lEl->TXT[0]==S1) {
if (lSc!=0) lSc=lSc->ADD(lEl);else lSc=lEl ;
}
else if (lEl->TXT[0]==S2) {
lEl->DEL();lSc=lSc->ROD;if (lSc==iEl)lSc=0;
}// Поднимаемся на уровент наверх
else if (lSc!=0 ) lSc->ADD(lEl);
lEl=MEl;
}
}
void Debugr(TEl*iEl,string iOt) { // Выводит содержимое эдемента в консоль
TEl*lEl=iEl;
while (lEl!=0){
cout<<iOt<<lEl->TXT<<endl;
if (lEl->FIR!=0) Debugr(lEl->FIR,iOt+" ");
lEl=lEl->NEX;
}
}
void VlojPA(TEl*iEl) { // Вкладывает парметры нутрь функции
// Перебираемые элементы текущий элемент
TEl* lEl = iEl->FIR;
// Пока не встретим конец списка
while (lEl != 0) {
if (lEl->TIP==TI_SLO)
if ((lEl->NEX!=0)&&(lEl->NEX->TXT=="("))
lEl->ADD(lEl->NEX);else lEl->ADD("(",TI_ZNA);
VlojPA(lEl);
lEl = lEl->NEX;
}
}
void VlojBL(TEl*iEl) { // Вкладывает парметры нутрь функции
// Перебираемые элементы текущий элемент
TEl* lEl = iEl->FIR;
// Пока не встретим конец списка
while (lEl != 0) {
if (lEl->TIP==TI_SLO)
if (lEl->NEX!=0)
if (lEl->NEX->TXT=="{")
{
lEl->FUN=true;// Это функция
lEl->ADD(lEl->NEX);
}
VlojBL(lEl);
lEl = lEl->NEX;
}
}
void VlojZ1(TEl*iEl) { // Вкладывает знаки Умножение деление
// Перебираемые элементы текущий элемент
TEl* lEl = iEl->FIR;
// Пока не встретим конец списка
while (lEl != 0) {
if (lEl->NEX!=0)
if (lEl->PRE!=0)
if ((lEl->TXT=="*")||(lEl->TXT=="/")) {
lEl->ADD(lEl->PRE); // Пермещаю предыдущий элемент в ЗНАК */
lEl->ADD(lEl->NEX); // Пермещаю следующий элемент в ЗНАК */
}
if (lEl->FIR != 0) VlojZ1(lEl);
lEl = lEl->NEX;
}
}
void VlojZ2(TEl*iEl) { // Вкладывает знаки Умножение деление
// Перебираемые элементы текущий элемент
TEl* lEl = iEl->FIR;
// Пока не встретим конец списка
while (lEl != 0) {
if ((lEl->TXT=="+")||(lEl->TXT=="-"))
if (lEl->NEX!=0)
if (lEl->PRE!=0)
{
lEl->ADD(lEl->PRE); // Пермещаю предыдущий элемент в ЗНАК +-
lEl->ADD(lEl->NEX); // Пермещаю следующий элемент в ЗНАК +-
}
if (lEl->FIR != 0) VlojZ2(lEl);
lEl = lEl->NEX;
}
}
void VlojZ3(TEl*iEl) { // Вкладывает знаки присвоения
// Перебираемые элементы текущий элемент
TEl* lEl = iEl->FIR;
// Пока не встретим конец списка
while (lEl != 0) {
if (lEl->TXT==":=")
if (lEl->NEX!=0)
if (lEl->PRE!=0)
{
lEl->ADD(lEl->PRE); // Пермещаю предыдущий элемент в ЗНАК :=
lEl->ADD(lEl->NEX); // Пермещаю следующий элемент в ЗНАК :=
}
VlojZ3(lEl);
lEl = lEl->NEX;
}
}
int main(int argc, char** argv) {
STR prog=" A(){A:=1;} PRINT( (1+2)*A) ";// Текст программы
TEl*PRO=RedSlo(prog);// Разбиваем строку на слова
Vlojit(PRO,'[',']');// Вкладываем квадратные скобки
Vlojit(PRO,'(',')');// Вкладываем скобки
Vlojit(PRO,'{','}');// Вкладываем исполнительные блоки
VlojPA(PRO);// Вкладываем параметры функций
VlojBL(PRO);// Вкладываем исполнительне блоки
VlojZ1(PRO);// Вкладываем Умнеожения деления */
VlojZ2(PRO);// Вкладываем Сложения вычитания +-
VlojZ3(PRO);// Вкладываем операции присвоения :=
PRO->Runs();// Выполнить программу
Debugr(PRO," ");// Выводим содержимое элемента
cout << endl << endl; // ПРосто перевод строки
return 0;
}
@quickneed
Copy link

Спасибо !

@nek1kek
Copy link

nek1kek commented Jan 13, 2023

жесть

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment