Компактный парсер-транслятор формул на векторах
Помогите исправить.
Код:
#include <string>
#include "math.h"
#include <vector>
using namespace std;
enum Type { num,var,con, opb,clb, alu,alb,bou };//Возможные типы лексем
enum Moda { alg, dif };//Возможные модальности строк
typedef int Inst;//Инструкция парсеру
typedef int Prop;//Приоретет операции
struct Lexeme;
typedef long double Real;
typedef unsigned Unsi;
typedef vector<Real> Valu;
typedef vector<Lexeme*> Lxms;
typedef vector<Lexeme> Numb;
struct Lexlib;
typedef vector<Lexlib> Libr;
//---------------------------------------------------------------------------
struct Lexeme
{
Type T;
Inst I;
Prop P;
//-----------------------
Lexeme(Type t,Inst i,Prop p){T=t;I=i;P=p;}
};
struct Lexlib : Lexeme
{
string S;
//-----------------------
Lexlib(string s,Type t,Inst i,Prop p):Lexeme(t,i,p)
{S=s;}
};
//---------------------------------------------------------------------------
struct Library
{
Unsi M;//длина самого длинного слова
Libr L;
Valu C;
Valu V;
//-----------------------
void SetM(){
M = 0;
for(Unsi i=0;i<L.size();i++)
if (L.S.length() > M) M = L.S.length();
}
//-----------------------
Lexeme *Find(string s){
Lexeme *f;
for(Unsi i=0;i<L.size();i++)
if (L.S == s) f = &L;
return f;
}
//-----------------------
Library(){
//скобки
L.push_back(Lexlib("(",opb,1,0));
L.push_back(Lexlib("{",opb,1,0));
L.push_back(Lexlib("[",opb,1,0));
L.push_back(Lexlib(")",clb,2,0));
L.push_back(Lexlib("}",clb,2,0));
L.push_back(Lexlib("]",clb,2,0));
//арифметические
L.push_back(Lexlib("+",bou,-3,6));//if I=+3 -> P=2
L.push_back(Lexlib("-",bou,-4,6));//if I=+4 -> P=2
L.push_back(Lexlib("*",alb,5,3));
L.push_back(Lexlib("/",alb,6,3));
L.push_back(Lexlib("^",alb,7,4));
//функции
L.push_back(Lexlib("abs",alu,-8,6));//модуль
L.push_back(Lexlib("exp",alu,-9,6));//экспонента
L.push_back(Lexlib("ln",alu,-10,6));//натуральный логарифм
L.push_back(Lexlib("lg",alu,-11,6));//десятичный логарифм
L.push_back(Lexlib("log",alb,12,5));//логарифм по произвольному основанию
L.push_back(Lexlib("max",alb,13,5));//максимальное из двух чисел
L.push_back(Lexlib("min",alb,14,5));//минимальное из двух чисел
L.push_back(Lexlib("arccos",alu,-15,6));//арккосинус
L.push_back(Lexlib("arcsin",alu,-16,6));//арксинус
L.push_back(Lexlib("arctg",alu,-17,6));//арктангенс
L.push_back(Lexlib("arcctg",alu,-18,6));//арккотангенс
L.push_back(Lexlib("sin",alu,-19,6));//синус
L.push_back(Lexlib("cos",alu,-20,6));//косинус
L.push_back(Lexlib("tg",alu,-21,6));//тангенс
L.push_back(Lexlib("ctg",alu,-22,6));//котангенс
L.push_back(Lexlib("sh",alu,-23,6));//синус гиперболический
L.push_back(Lexlib("ch",alu,-24,6));//косинус гиперболический
L.push_back(Lexlib("th",alu,-25,6));//тангенс гиперболический
L.push_back(Lexlib("cth",alu,-26,6));//котангенс гиперболический
L.push_back(Lexlib("arcsh",alu,-27,6));//арксинус гиперболический
L.push_back(Lexlib("arcch",alu,-28,6));//арккосинус гиперболический
L.push_back(Lexlib("arcth",alu,-29,6));//арктангенс гиперболический
L.push_back(Lexlib("arccth",alu,-30,6));//арккотангенс гиперболический
//константы
L.push_back(Lexlib("pi",con,C.size(),0));//число пи
C.push_back(M_PI);
SetM();
}
//-----------------------
} Lib;
//---------------------------------------------------------------------------
struct Baseline
{
string K;
Moda D;
Valu V;//числовые значения
Numb N;//вектор лексем
//-----------------------
void Analyses(){
int cbr=0;//счетчик скобок
for (Unsi i=0;i<N.size();i++){
if(N.T==opb)cbr++; if(N.T==clb)cbr--;
if(i==0){
if(N.T==clb || N.T==alb)ShowMessage("Недопустима лексема в начале!"), Abort();
}else{
if(N.T==opb &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед '('!"), Abort();
if((N.T==num || N.T==var || N.T==con) &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед числом!"), Abort();
if(N.T==alb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед бинарной операцией!"), Abort();
if(N.T==clb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед ')'!"), Abort();
if(N.T==alu &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед унарной операцией!"), Abort();
if(N.T==bou &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))N.I = -N.I, N.P = 2;
}
if(i==(N.size()-1)){
if((N.T != clb) && (N.T != num) &&
(N.T != var) && (N.T != con))ShowMessage("Недопустима лексема в конце!"), Abort();
}
}
if(cbr != 0)ShowMessage("Несоответствие скобок!"), Abort();
}
//-----------------------
Real Get_num(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];}
return (Real)_strtold(chislo.c_str(),NULL);
}
//-----------------------
string Get_str(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];} return chislo;
}
//-----------------------
void fcalc(Valu &st, int op){
if (op < 0) {
Real l = st.back(); st.pop_back();
switch (-op) {
case 3: st.push_back (l); break;
case 4: st.push_back (-l); break;
}
}else {
Real r = st.back(); st.pop_back();
Real l = st.back(); st.pop_back();
switch (op) {
case 3: st.push_back (l + r); break;
case 4: st.push_back (l - r); break;
case 5: st.push_back (l * r); break;
case 6: if(r!=0)st.push_back (l / r);
else ShowMessage("Попытка деления на ноль!"), Abort(); break;
}
}
}
//-----------------------
Real ParsIt(){
Valu st; Lxms op;// Code
for (Unsi i=0; i<N.size(); ++i)//идем вдоль строки
if(N.T == opb)op.push_back (&N);
else
if(N.T == clb){
while((*op.back()).T != opb) fcalc(st,(*op.back()).I), op.pop_back();
op.pop_back();
}else
if (N.T == bou || N.T == alu || N.T == alb){
while(!op.empty() &&
( N.I >= 0 && ((*op.back()).P >= N.P) ||
N.I < 0 && ((*op.back()).P > N.P)) )
fcalc(st, (*op.back()).I), op.pop_back();
op.push_back(&N);
}
else
if (N.T == num)
{
st.push_back (V[N.I]);
}
else
if (N.T == var)
{
st.push_back (Lib.V[N.I]);
}
else
if (N.T == con)
{
st.push_back (Lib.C[N.I]);
}
while (!op.empty())
fcalc(st,(*op.back()).I), op.pop_back();
return st.back();
}
//-----------------------
void Translate(string s){
Unsi curL;//длина оставшейся части строки
string stp;//строка_пробная;
Type code;
Lexeme *f;
curL = s.length();//определяем длину строки
if(curL>Lib.M)
for (Unsi i=0;i<Lib.M;i++)stp += s;//берем первые M символов
else
stp = s; f = Lib.Find(stp); code = f->T;
if(code > 0){//если найдена
N.push_back(Lexeme(f->T,f->I,f->P));
K.erase(0,stp.length());//удаляем из строки stp.length() символов
curL = K.length();
if
#include "math.h"
#include <vector>
using namespace std;
enum Type { num,var,con, opb,clb, alu,alb,bou };//Возможные типы лексем
enum Moda { alg, dif };//Возможные модальности строк
typedef int Inst;//Инструкция парсеру
typedef int Prop;//Приоретет операции
struct Lexeme;
typedef long double Real;
typedef unsigned Unsi;
typedef vector<Real> Valu;
typedef vector<Lexeme*> Lxms;
typedef vector<Lexeme> Numb;
struct Lexlib;
typedef vector<Lexlib> Libr;
//---------------------------------------------------------------------------
struct Lexeme
{
Type T;
Inst I;
Prop P;
//-----------------------
Lexeme(Type t,Inst i,Prop p){T=t;I=i;P=p;}
};
struct Lexlib : Lexeme
{
string S;
//-----------------------
Lexlib(string s,Type t,Inst i,Prop p):Lexeme(t,i,p)
{S=s;}
};
//---------------------------------------------------------------------------
struct Library
{
Unsi M;//длина самого длинного слова
Libr L;
Valu C;
Valu V;
//-----------------------
void SetM(){
M = 0;
for(Unsi i=0;i<L.size();i++)
if (L.S.length() > M) M = L.S.length();
}
//-----------------------
Lexeme *Find(string s){
Lexeme *f;
for(Unsi i=0;i<L.size();i++)
if (L.S == s) f = &L;
return f;
}
//-----------------------
Library(){
//скобки
L.push_back(Lexlib("(",opb,1,0));
L.push_back(Lexlib("{",opb,1,0));
L.push_back(Lexlib("[",opb,1,0));
L.push_back(Lexlib(")",clb,2,0));
L.push_back(Lexlib("}",clb,2,0));
L.push_back(Lexlib("]",clb,2,0));
//арифметические
L.push_back(Lexlib("+",bou,-3,6));//if I=+3 -> P=2
L.push_back(Lexlib("-",bou,-4,6));//if I=+4 -> P=2
L.push_back(Lexlib("*",alb,5,3));
L.push_back(Lexlib("/",alb,6,3));
L.push_back(Lexlib("^",alb,7,4));
//функции
L.push_back(Lexlib("abs",alu,-8,6));//модуль
L.push_back(Lexlib("exp",alu,-9,6));//экспонента
L.push_back(Lexlib("ln",alu,-10,6));//натуральный логарифм
L.push_back(Lexlib("lg",alu,-11,6));//десятичный логарифм
L.push_back(Lexlib("log",alb,12,5));//логарифм по произвольному основанию
L.push_back(Lexlib("max",alb,13,5));//максимальное из двух чисел
L.push_back(Lexlib("min",alb,14,5));//минимальное из двух чисел
L.push_back(Lexlib("arccos",alu,-15,6));//арккосинус
L.push_back(Lexlib("arcsin",alu,-16,6));//арксинус
L.push_back(Lexlib("arctg",alu,-17,6));//арктангенс
L.push_back(Lexlib("arcctg",alu,-18,6));//арккотангенс
L.push_back(Lexlib("sin",alu,-19,6));//синус
L.push_back(Lexlib("cos",alu,-20,6));//косинус
L.push_back(Lexlib("tg",alu,-21,6));//тангенс
L.push_back(Lexlib("ctg",alu,-22,6));//котангенс
L.push_back(Lexlib("sh",alu,-23,6));//синус гиперболический
L.push_back(Lexlib("ch",alu,-24,6));//косинус гиперболический
L.push_back(Lexlib("th",alu,-25,6));//тангенс гиперболический
L.push_back(Lexlib("cth",alu,-26,6));//котангенс гиперболический
L.push_back(Lexlib("arcsh",alu,-27,6));//арксинус гиперболический
L.push_back(Lexlib("arcch",alu,-28,6));//арккосинус гиперболический
L.push_back(Lexlib("arcth",alu,-29,6));//арктангенс гиперболический
L.push_back(Lexlib("arccth",alu,-30,6));//арккотангенс гиперболический
//константы
L.push_back(Lexlib("pi",con,C.size(),0));//число пи
C.push_back(M_PI);
SetM();
}
//-----------------------
} Lib;
//---------------------------------------------------------------------------
struct Baseline
{
string K;
Moda D;
Valu V;//числовые значения
Numb N;//вектор лексем
//-----------------------
void Analyses(){
int cbr=0;//счетчик скобок
for (Unsi i=0;i<N.size();i++){
if(N.T==opb)cbr++; if(N.T==clb)cbr--;
if(i==0){
if(N.T==clb || N.T==alb)ShowMessage("Недопустима лексема в начале!"), Abort();
}else{
if(N.T==opb &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед '('!"), Abort();
if((N.T==num || N.T==var || N.T==con) &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед числом!"), Abort();
if(N.T==alb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед бинарной операцией!"), Abort();
if(N.T==clb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед ')'!"), Abort();
if(N.T==alu &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед унарной операцией!"), Abort();
if(N.T==bou &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))N.I = -N.I, N.P = 2;
}
if(i==(N.size()-1)){
if((N.T != clb) && (N.T != num) &&
(N.T != var) && (N.T != con))ShowMessage("Недопустима лексема в конце!"), Abort();
}
}
if(cbr != 0)ShowMessage("Несоответствие скобок!"), Abort();
}
//-----------------------
Real Get_num(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];}
return (Real)_strtold(chislo.c_str(),NULL);
}
//-----------------------
string Get_str(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];} return chislo;
}
//-----------------------
void fcalc(Valu &st, int op){
if (op < 0) {
Real l = st.back(); st.pop_back();
switch (-op) {
case 3: st.push_back (l); break;
case 4: st.push_back (-l); break;
}
}else {
Real r = st.back(); st.pop_back();
Real l = st.back(); st.pop_back();
switch (op) {
case 3: st.push_back (l + r); break;
case 4: st.push_back (l - r); break;
case 5: st.push_back (l * r); break;
case 6: if(r!=0)st.push_back (l / r);
else ShowMessage("Попытка деления на ноль!"), Abort(); break;
}
}
}
//-----------------------
Real ParsIt(){
Valu st; Lxms op;// Code
for (Unsi i=0; i<N.size(); ++i)//идем вдоль строки
if(N.T == opb)op.push_back (&N);
else
if(N.T == clb){
while((*op.back()).T != opb) fcalc(st,(*op.back()).I), op.pop_back();
op.pop_back();
}else
if (N.T == bou || N.T == alu || N.T == alb){
while(!op.empty() &&
( N.I >= 0 && ((*op.back()).P >= N.P) ||
N.I < 0 && ((*op.back()).P > N.P)) )
fcalc(st, (*op.back()).I), op.pop_back();
op.push_back(&N);
}
else
if (N.T == num)
{
st.push_back (V[N.I]);
}
else
if (N.T == var)
{
st.push_back (Lib.V[N.I]);
}
else
if (N.T == con)
{
st.push_back (Lib.C[N.I]);
}
while (!op.empty())
fcalc(st,(*op.back()).I), op.pop_back();
return st.back();
}
//-----------------------
void Translate(string s){
Unsi curL;//длина оставшейся части строки
string stp;//строка_пробная;
Type code;
Lexeme *f;
curL = s.length();//определяем длину строки
if(curL>Lib.M)
for (Unsi i=0;i<Lib.M;i++)stp += s;//берем первые M символов
else
stp = s; f = Lib.Find(stp); code = f->T;
if(code > 0){//если найдена
N.push_back(Lexeme(f->T,f->I,f->P));
K.erase(0,stp.length());//удаляем из строки stp.length() символов
curL = K.length();
if
А есть этот же код [COLOR="silver"]но с розовыми пуговицами?[/COLOR] но в хорошо отформатированном виде?
Ниже представлен проблемный вариант, с указанием места неправильной работы.
[COLOR="gray"]Это мое наследие, моя 7-я симфония, моя Эйфелева башня...[/COLOR]
Код:
#include <string>
#include "math.h"
#include <vector>
using namespace std;
enum Type { num,var,con, opb,clb, alu,alb,bou };//Возможные типы лексем
/*num-числовые,var-переменные,con-константы,
opb-открывающие скобки,clb-закрывающие скобки,
alu-всегда унарные,alb-всегда бинарные,bou-бинарно-унарные*/
enum Moda { alg, dif };//Возможные модальности строк
typedef int Inst;//Инструкция парсеру
typedef int Prop;//Приоретет операции
struct Lexeme;
typedef long double Real;
typedef unsigned Unsi;
typedef vector<Real> Valu;
typedef vector<Lexeme*> Lxms;
typedef vector<Lexeme> Numb;
typedef vector<Lexeme> Libr;
//---------------------------------------------------------------------------
struct Lexeme
{
string S;
Type T;
Inst I;
Prop P;
//-----------------------
Lexeme(string s,Type t,Inst i,Prop p){S=s;T=t;I=i;P=p;}
};
//---------------------------------------------------------------------------
struct Library
{
Unsi M;//длина самого длинного слова
Libr L;
Valu C;
Valu V;
//-----------------------
void SetM(){
M = 0;
for(Unsi i=0;i<L.size();i++)
if (L.S.length() > M) M = L.S.length();
}
//-----------------------
Lexeme *Find(string s){
Lexeme *f;
for(Unsi i=0;i<L.size();i++)
if (L.S == s) f = &L;
return f;
}
//-----------------------
Library(){
//скобки
L.push_back(Lexeme("(",opb,1,0));
L.push_back(Lexeme("{",opb,1,0));
L.push_back(Lexeme("[",opb,1,0));
L.push_back(Lexeme(")",clb,2,0));
L.push_back(Lexeme("}",clb,2,0));
L.push_back(Lexeme("]",clb,2,0));
//арифметические
L.push_back(Lexeme("+",bou,-3,6));//if I=+3 -> P=2
L.push_back(Lexeme("-",bou,-4,6));//if I=+4 -> P=2
L.push_back(Lexeme("*",alb,5,3));
L.push_back(Lexeme("/",alb,6,3));
L.push_back(Lexeme("^",alb,7,4));
//функции
L.push_back(Lexeme("abs",alu,-8,6));//модуль
L.push_back(Lexeme("exp",alu,-9,6));//экспонента
L.push_back(Lexeme("ln",alu,-10,6));//натуральный логарифм
L.push_back(Lexeme("lg",alu,-11,6));//десятичный логарифм
L.push_back(Lexeme("log",alb,12,5));//логарифм по произвольному основанию
L.push_back(Lexeme("max",alb,13,5));//максимальное из двух чисел
L.push_back(Lexeme("min",alb,14,5));//минимальное из двух чисел
L.push_back(Lexeme("arccos",alu,-15,6));//арккосинус
L.push_back(Lexeme("arcsin",alu,-16,6));//арксинус
L.push_back(Lexeme("arctg",alu,-17,6));//арктангенс
L.push_back(Lexeme("arcctg",alu,-18,6));//арккотангенс
//константы
L.push_back(Lexeme("pi",con,C.size(),0));//число пи
C.push_back(M_PI);
SetM();
}
//-----------------------
} Lib;
//---------------------------------------------------------------------------
struct Baseline
{
string K;
Moda D;
Valu V;//числовые значения
Numb N;//вектор лексем
//-----------------------
void Analyses(){
int cbr=0;//счетчик скобок
for (Unsi i=0;i<N.size();i++){
if(N.T==opb)cbr++; if(N.T==clb)cbr--;
if(i==0){
if(N.T==clb || N.T==alb)ShowMessage("Недопустима лексема в начале!"), Abort();
}else{
if(N.T==opb &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед '('!"), Abort();
if((N.T==num || N.T==var || N.T==con) &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед числом!"), Abort();
if(N.T==alb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед бинарной операцией!"), Abort();
if(N.T==clb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед ')'!"), Abort();
if(N.T==alu &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед унарной операцией!"), Abort();
if(N.T==bou &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))N.I = -N.I, N.P = 2;
}
if(i==(N.size()-1)){
if((N.T != clb) && (N.T != num) &&
(N.T != var) && (N.T != con))ShowMessage("Недопустима лексема в конце!"), Abort();//<-если строка пуста, то это выскакивает
}
}
if(cbr != 0)ShowMessage("Несоответствие скобок!"), Abort();
}
//-----------------------
Real Get_num(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];}
return (Real)_strtold(chislo.c_str(),NULL);
}
//-----------------------
string Get_str(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];} return chislo;
}
//-----------------------
void fcalc(Valu &st, int op){
if (op < 0) {
Real l = st.back(); st.pop_back();
switch (-op) {
case 3: st.push_back (l); break;
case 4: st.push_back (-l); break;
}
}else {
Real r = st.back(); st.pop_back();
Real l = st.back(); st.pop_back();
switch (op) {
case 3: st.push_back (l + r); break;
case 4: st.push_back (l - r); break;
case 5: st.push_back (l * r); break;
case 6: if(r!=0)st.push_back (l / r);
else ShowMessage("Попытка деления на ноль!"), Abort(); break;
}
}
}
//-----------------------
Real ParsIt(){
Valu st; Lxms op;// Code
for (Unsi i=0; i<N.size(); ++i)//идем вдоль строки
if(N.T == opb)op.push_back (&N);
else
if(N.T == clb){
while((*op.back()).T != opb) fcalc(st,(*op.back()).I), op.pop_back();
op.pop_back();
}else
if (N.T == bou || N.T == alu || N.T == alb){
while(!op.empty() &&
( N.I >= 0 && ((*op.back()).P >= N.P) ||
N.I < 0 && ((*op.back()).P > N.P)) )
fcalc(st, (*op.back()).I), op.pop_back();
op.push_back(&N);
}
else
if (N.T == num) st.push_back (V[N.I]);
else
if (N.T == var) st.push_back (Lib.V[N.I]);
else
if (N.T == con) st.push_back (Lib.C[N.I]);
while (!op.empty()) fcalc(st,(*op.back()).I), op.pop_back();
return st.back();
}
//-----------------------
void Translate(string s){
Unsi curL;//длина оставшейся части строки
string stp;//строка_пробная;
Type code;
Lexeme *f;
curL = s.length();//определяем длину строки
if(curL>Lib.M)
for (Unsi i=0;i<Lib.M;i++)stp += s;//берем первые M символов
else
stp = s; f = Lib.Find(stp); code = f->T;
if(code > 0){//если найдена
N.push_back(Lexeme(f->S,f->T,f->I,f->P));//<-не инициализируется нормально
K.erase(0,stp.length());//удаляем из строки stp.length() символов
curL = K.length();
if( curL > 0)
Translate(K);
}
else {//если не найдена
if(stp.length() > 1){
stp.erase(stp.length()-1,1);//удаляем из stp 1 символ
Translate(stp);
}else{
if(stp[0] == ' ')ShowMessage("Пробел не допустим!"), Abort();
else
if(!isdigit(stp[0]) && (stp.length() != 0) && stp[0] != ' ')
{ AnsiString err; err = stp.c_str();
ShowMessage("Не допустимый символ: " + err), Abort();
}else{
N.push_back(Lexeme(Get_str(K),num,V.size(),0));
V.push_back(Get_num(K));//записываем в стуктуру хранящую числа значение strtod(chislo,NULL) ;
K.erase(0,Get_str(K).length()); curL = K.length();
if( curL > 0) Translate(K);
}
}
}
}
//-----------------------
Baseline(AnsiString str){K
#include "math.h"
#include <vector>
using namespace std;
enum Type { num,var,con, opb,clb, alu,alb,bou };//Возможные типы лексем
/*num-числовые,var-переменные,con-константы,
opb-открывающие скобки,clb-закрывающие скобки,
alu-всегда унарные,alb-всегда бинарные,bou-бинарно-унарные*/
enum Moda { alg, dif };//Возможные модальности строк
typedef int Inst;//Инструкция парсеру
typedef int Prop;//Приоретет операции
struct Lexeme;
typedef long double Real;
typedef unsigned Unsi;
typedef vector<Real> Valu;
typedef vector<Lexeme*> Lxms;
typedef vector<Lexeme> Numb;
typedef vector<Lexeme> Libr;
//---------------------------------------------------------------------------
struct Lexeme
{
string S;
Type T;
Inst I;
Prop P;
//-----------------------
Lexeme(string s,Type t,Inst i,Prop p){S=s;T=t;I=i;P=p;}
};
//---------------------------------------------------------------------------
struct Library
{
Unsi M;//длина самого длинного слова
Libr L;
Valu C;
Valu V;
//-----------------------
void SetM(){
M = 0;
for(Unsi i=0;i<L.size();i++)
if (L.S.length() > M) M = L.S.length();
}
//-----------------------
Lexeme *Find(string s){
Lexeme *f;
for(Unsi i=0;i<L.size();i++)
if (L.S == s) f = &L;
return f;
}
//-----------------------
Library(){
//скобки
L.push_back(Lexeme("(",opb,1,0));
L.push_back(Lexeme("{",opb,1,0));
L.push_back(Lexeme("[",opb,1,0));
L.push_back(Lexeme(")",clb,2,0));
L.push_back(Lexeme("}",clb,2,0));
L.push_back(Lexeme("]",clb,2,0));
//арифметические
L.push_back(Lexeme("+",bou,-3,6));//if I=+3 -> P=2
L.push_back(Lexeme("-",bou,-4,6));//if I=+4 -> P=2
L.push_back(Lexeme("*",alb,5,3));
L.push_back(Lexeme("/",alb,6,3));
L.push_back(Lexeme("^",alb,7,4));
//функции
L.push_back(Lexeme("abs",alu,-8,6));//модуль
L.push_back(Lexeme("exp",alu,-9,6));//экспонента
L.push_back(Lexeme("ln",alu,-10,6));//натуральный логарифм
L.push_back(Lexeme("lg",alu,-11,6));//десятичный логарифм
L.push_back(Lexeme("log",alb,12,5));//логарифм по произвольному основанию
L.push_back(Lexeme("max",alb,13,5));//максимальное из двух чисел
L.push_back(Lexeme("min",alb,14,5));//минимальное из двух чисел
L.push_back(Lexeme("arccos",alu,-15,6));//арккосинус
L.push_back(Lexeme("arcsin",alu,-16,6));//арксинус
L.push_back(Lexeme("arctg",alu,-17,6));//арктангенс
L.push_back(Lexeme("arcctg",alu,-18,6));//арккотангенс
//константы
L.push_back(Lexeme("pi",con,C.size(),0));//число пи
C.push_back(M_PI);
SetM();
}
//-----------------------
} Lib;
//---------------------------------------------------------------------------
struct Baseline
{
string K;
Moda D;
Valu V;//числовые значения
Numb N;//вектор лексем
//-----------------------
void Analyses(){
int cbr=0;//счетчик скобок
for (Unsi i=0;i<N.size();i++){
if(N.T==opb)cbr++; if(N.T==clb)cbr--;
if(i==0){
if(N.T==clb || N.T==alb)ShowMessage("Недопустима лексема в начале!"), Abort();
}else{
if(N.T==opb &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед '('!"), Abort();
if((N.T==num || N.T==var || N.T==con) &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед числом!"), Abort();
if(N.T==alb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед бинарной операцией!"), Abort();
if(N.T==clb &&
(N[i-1].T!=clb && N[i-1].T!=num &&
N[i-1].T!=var && N[i-1].T!=con))ShowMessage("Недопустимая лексема перед ')'!"), Abort();
if(N.T==alu &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))ShowMessage("Недопустимая лексема перед унарной операцией!"), Abort();
if(N.T==bou &&
(N[i-1].T==clb || N[i-1].T==num ||
N[i-1].T==var || N[i-1].T==con))N.I = -N.I, N.P = 2;
}
if(i==(N.size()-1)){
if((N.T != clb) && (N.T != num) &&
(N.T != var) && (N.T != con))ShowMessage("Недопустима лексема в конце!"), Abort();//<-если строка пуста, то это выскакивает
}
}
if(cbr != 0)ShowMessage("Несоответствие скобок!"), Abort();
}
//-----------------------
Real Get_num(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];}
return (Real)_strtold(chislo.c_str(),NULL);
}
//-----------------------
string Get_str(string st){
string chislo; Unsi j = 0;
while ((st[j] == ',' || st[j] == '.' || isdigit (st[j])) && (st.length() - j) > 0){
if (st[j] == ',') st[j] = '.'; chislo += st[j++];} return chislo;
}
//-----------------------
void fcalc(Valu &st, int op){
if (op < 0) {
Real l = st.back(); st.pop_back();
switch (-op) {
case 3: st.push_back (l); break;
case 4: st.push_back (-l); break;
}
}else {
Real r = st.back(); st.pop_back();
Real l = st.back(); st.pop_back();
switch (op) {
case 3: st.push_back (l + r); break;
case 4: st.push_back (l - r); break;
case 5: st.push_back (l * r); break;
case 6: if(r!=0)st.push_back (l / r);
else ShowMessage("Попытка деления на ноль!"), Abort(); break;
}
}
}
//-----------------------
Real ParsIt(){
Valu st; Lxms op;// Code
for (Unsi i=0; i<N.size(); ++i)//идем вдоль строки
if(N.T == opb)op.push_back (&N);
else
if(N.T == clb){
while((*op.back()).T != opb) fcalc(st,(*op.back()).I), op.pop_back();
op.pop_back();
}else
if (N.T == bou || N.T == alu || N.T == alb){
while(!op.empty() &&
( N.I >= 0 && ((*op.back()).P >= N.P) ||
N.I < 0 && ((*op.back()).P > N.P)) )
fcalc(st, (*op.back()).I), op.pop_back();
op.push_back(&N);
}
else
if (N.T == num) st.push_back (V[N.I]);
else
if (N.T == var) st.push_back (Lib.V[N.I]);
else
if (N.T == con) st.push_back (Lib.C[N.I]);
while (!op.empty()) fcalc(st,(*op.back()).I), op.pop_back();
return st.back();
}
//-----------------------
void Translate(string s){
Unsi curL;//длина оставшейся части строки
string stp;//строка_пробная;
Type code;
Lexeme *f;
curL = s.length();//определяем длину строки
if(curL>Lib.M)
for (Unsi i=0;i<Lib.M;i++)stp += s;//берем первые M символов
else
stp = s; f = Lib.Find(stp); code = f->T;
if(code > 0){//если найдена
N.push_back(Lexeme(f->S,f->T,f->I,f->P));//<-не инициализируется нормально
K.erase(0,stp.length());//удаляем из строки stp.length() символов
curL = K.length();
if( curL > 0)
Translate(K);
}
else {//если не найдена
if(stp.length() > 1){
stp.erase(stp.length()-1,1);//удаляем из stp 1 символ
Translate(stp);
}else{
if(stp[0] == ' ')ShowMessage("Пробел не допустим!"), Abort();
else
if(!isdigit(stp[0]) && (stp.length() != 0) && stp[0] != ' ')
{ AnsiString err; err = stp.c_str();
ShowMessage("Не допустимый символ: " + err), Abort();
}else{
N.push_back(Lexeme(Get_str(K),num,V.size(),0));
V.push_back(Get_num(K));//записываем в стуктуру хранящую числа значение strtod(chislo,NULL) ;
K.erase(0,Get_str(K).length()); curL = K.length();
if( curL > 0) Translate(K);
}
}
}
}
//-----------------------
Baseline(AnsiString str){K