Старожил
Сообщения: 232
Благодарности: 90
|
Профиль
|
Сайт
|
Отправить PM
| Цитировать
Вот вам арифметический анализатор:
Код: ![Выделить весь код](images/misc/selectcode.png)
#ifndef __PARSER_H
#define __PARSER_H
#include <iostream>
#include <math.h>
#include <map>
#include <string>
#include <iomanip>
using namespace std;
typedef map<string,double> tVr;
enum Tokens { DELIMITER = 1, VARIABLE, NUMBER, FUNCTION };
enum Function { SIN=5, COS, EXP, LN, LOG10, TAN, SQRT, FABS, ASIN, ACOS, ATAN,
SINH, COSH, TANH, FACT, LOG, FMOD, CEIL, FLOOR, SECANT, COSECANT,
COTAN, ASEC, ACOSEC, ACOTAN, COSECH, COTANH, ASINH, ACOSH, ATANH,
ASECH, ACOSECH, ACOTANH };
#define NUMVARS 26
template <class PType>
class CParser
{
char* exp_ptr;
char token[80];
char tok_type;
char fun_type;
string cur_var;
tVr vars;
bool IsErr;
void eval_exp1(PType& result);
void eval_exp2(PType& result);
void eval_exp3(PType& result);
void eval_exp4(PType& result);
void eval_exp5(PType& result);
void eval_exp6(PType& result);
void atom(PType& result);
void get_token(),putback();
void serror(int error);
PType find_var(string s);
int isdelim(char c);
friend long fact(long n);
friend PType DecTo();
public:
CParser();
~CParser();
PType eval_exp(char* exp);
tVr GetVars();
void SetValue(string var,PType& value);
PType GetValue(string var);
bool IsError();
};
long fact(long n)
{
if( (n == 0) || (n == 1) ) return 1;
return ( n * fact(n-1) );
}
template <class PType>
CParser<PType>::CParser()
{
exp_ptr = NULL;
vars["E"] = 2.71828182845904523536;
vars["PI"] = 3.14159265358979323846;
vars["x"] = 0;
}
template <class PType>
CParser<PType>::~CParser()
{
exp_ptr = NULL;
}
template <class PType>
PType CParser<PType>::eval_exp(char* exp)
{
PType result = (PType) 0;
exp_ptr = exp;
IsErr = false;
get_token();
if ( !*token )
{
serror(2);
return (PType) 0;
}
eval_exp1(result);
if (*token) serror (0);
if( IsError() ) return (PType) 0;
else return (PType) result;
}
template <class PType>
void CParser<PType>::eval_exp1(PType& result)
{
char ttok_type;
char temp_token[80];
string var;
if ( tok_type == VARIABLE)
{
strcpy(temp_token,token);
ttok_type = tok_type;
var = cur_var;
get_token();
if (*token != '=')
{
putback();
strcpy(token,temp_token);
tok_type = ttok_type;
}
else
{
get_token();
eval_exp2(result);
if( (var == "E") || (var == "PI") ) serror(72);
else vars[var] = result;
return;
}
}
eval_exp2(result);
}
template <class PType>
void CParser<PType>::eval_exp2(PType& result)
{
register char op;
PType temp;
temp = (PType) 0;
eval_exp3(result);
while( (op = *token) == '+' || op == '-')
{
get_token();
eval_exp3(temp);
switch(op)
{
case '-': result = result - temp; break;
case '+': result = result + temp; break;
}
}
}
template <class PType>
void CParser<PType>::eval_exp3(PType& result)
{
register char op;
PType temp;
temp = (PType) 0;
eval_exp4(result);
while( (op = *token) == '*' || op == '/' || op == '%')
{
get_token();
eval_exp4(temp);
switch(op)
{
case '*': result = result * temp; break;
case '/': result = result / temp; break;
case '%': result = (int) result % (int) temp; break;
}
}
}
template <class PType>
void CParser<PType>::eval_exp4(PType& result)
{
PType temp;
temp =(PType) 0;
eval_exp5(result);
if (*token == '^')
{
get_token();
eval_exp4(temp);
if (temp == 0.0)
{
result = (PType) 1;
return;
}
result = (PType) pow(result,temp);
}
}
template <class PType>
void CParser<PType>::eval_exp5(PType& result)
{
register char op;
op = 0;
if ( (tok_type == DELIMITER) && *token == '+' || *token == '-')
{
op = *token;
get_token();
}
eval_exp6(result);
if (op == '-') result = -result;
}
template <class PType>
void CParser<PType>::eval_exp6(PType& result)
{
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' )
serror(1);
get_token();
}
else atom(result);
}
template <class PType>
void CParser<PType>::atom(PType& result)
{
static PType arg1=0,arg2=0;
switch (tok_type)
{
case VARIABLE: result = find_var(cur_var); get_token(); return;
case NUMBER: result = (PType) atof(token); get_token(); return;
case FUNCTION:
switch(fun_type)
{
case SIN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(5);
else result = (PType) sin(result);
} else serror(4);
get_token(); return;
case COS: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(7);
else result = (PType) cos(result);
} else serror(6);
get_token(); return;
case EXP: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(9);
else result = (PType) exp(result);
} else serror(8);
get_token(); return;
case LN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(11);
else result = (PType) log(result);
} else serror(10);
get_token(); return;
case LOG10: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(13);
else result = (PType) log10(result);
} else serror(12);
get_token(); return;
case TAN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(15);
else result = (PType) tan(result);
} else serror(14);
get_token(); return;
case SQRT: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(17);
else result = (PType) sqrt(result);
} else serror(16);
get_token(); return;
case FABS: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(19);
else result = (PType) fabs(result);
} else serror(18);
get_token(); return;
case ASIN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(21);
else result = (PType) asin(result);
} else serror(20);
get_token(); return;
case ACOS: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(23);
else result = (PType) acos(result);
} else serror(22);
get_token(); return;
case ATAN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(25);
else result = (PType) atan(result);
} else serror(24);
get_token(); return;
case SINH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(27);
else result = (PType) sinh(result);
} else serror(26);
get_token(); return;
case COSH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(29);
else result = (PType) cosh(result);
} else serror(28);
get_token(); return;
case TANH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(31);
else result = (PType) tanh(result);
} else serror(30);
get_token(); return;
case FACT: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(33);
else result = (PType) fact(result);
} else serror(32);
get_token(); return;
case LOG: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(arg1);
if ( *token != ',' ) serror(36);
else {
get_token();
eval_exp2(arg2);
if ( *token != ')' ) serror(35);
else result = (PType) log10(arg1)/log10(arg2);
}
} else serror(34);
get_token(); return;
case FMOD: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(arg1);
if ( *token != ',' ) serror(39);
else
{
get_token();
eval_exp2(arg2);
if ( *token != ')' ) serror(38);
else result = (PType) fmod(arg1,arg2);
}
} else serror(37);
get_token(); return;
case CEIL: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(41);
else result = (PType) ceil(result);
} else serror(40);
get_token(); return;
case FLOOR: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(43);
else result = (PType) floor(result);
} else serror(42);
get_token(); return;
case SECANT: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(45);
else result = (PType) 1/cos(result);
} else serror(44);
get_token(); return;
case COSECANT: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(47);
else result = (PType) 1/sin(result);
} else serror(46);
get_token(); return;
case COTAN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(49);
else result = (PType) 1/tan(result);
} else serror(48);
get_token(); return;
case ASEC: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(51);
else result = (PType) atan( result / ((result * result - 1)*(result * result - 1)) ) + signed((result) -1) * (2 * atan((PType)1) );
} else serror(50);
get_token(); return;
case ACOSEC: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(53);
else result = (PType) atan(result / (result * result - 1)*(result * result - 1)) + (signed(result) - 1) * (2 * atan((PType)1));
} else serror(52);
get_token(); return;
case ACOTAN: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(55);
else result = (PType) atan(result) + 2 * atan((PType)1);
} else serror(54);
get_token(); return;
case COSECH:get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(57);
else result = (PType) 2/( exp(result) - exp(-result) );
} else serror(56);
get_token(); return;
case COTANH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(59);
else result = (PType) ( exp(result) + exp(-result) ) / ( exp(result) - exp(-result) );
} else serror(58);
get_token(); return;
case ASINH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(61);
else result = (PType) log(result + (result * result + 1)*(result * result + 1));
} else serror(60);
get_token(); return;
case ACOSH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(63);
else result = (PType) log(result + (result * result - 1)*(result * result - 1));
} else serror(62);
get_token(); return;
case ATANH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(65);
else result = (PType) log( (1 + result) / (1 - result) ) / 2;
} else serror(64);
get_token(); return;
case ASECH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(67);
else result = (PType) log( ( (-result * result + 1)*(-result * result + 1) + 1 ) / result);
} else serror(66);
get_token(); return;
case ACOSECH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(69);
else result = (PType) log((signed(result) * (result * result + 1)*(result * result + 1) +1) / result);
} else serror(68);
get_token(); return;
case ACOTANH: get_token();
if ( *token == '(' )
{
get_token();
eval_exp2(result);
if ( *token != ')' ) serror(71);
else result = (PType) log((result + 1) / (result - 1)) / 2;
} else serror(70);
get_token(); return;
default: serror(0);
}
default: serror(0);
}
}
template <class PType>
void CParser<PType>::putback()
{
char* t;
t = token;
for( ; *t; t++) exp_ptr--;
}
template <class PType>
void CParser<PType>::serror(int error)
{
IsErr = true;
static char *e[] =
{
"Parsing error",
"Breake balance of brackets",
"Expretion is empty",
"Undefine variable",
"SIN can't be a variable",
"Breake balance of SIN brackets",
"COS can't be a variable",
"Breake balance of COS brackets",
"EXP can't be a variable",
"Breake balance of EXP brackets",
"LN can't be a variable",
"Breake balance of LN brackets",
"LOG10 can't be a variable",
"Breake balance of LOG10 brackets",
"TAN can't be a variable",
"Breake balance of TAN brackets",
"SQRT can't be a variable",
"Breake balance of SQRT brackets",
"ABS can't be a variable",
"Breake balance of ABS brackets",
"ASIN can't be a variable",
"Breake balance of ASIN brackets",
"ACOS can't be a variable",
"Breake balance of ACOS brackets",
"ATAN can't be a variable",
"Breake balance of ATAN brackets",
"SINH can't be a variable",
"Breake balance of SINH brackets",
"COSH can't be a variable",
"Breake balance of COSH brackets",
"TANH can't be a variable",
"Breake balance of TANH brackets",
"FACT can't be a variable",
"Breake balance of FACT brackets",
"LOG can't be a variable",
"Breake balance of LOG brackets",
"LOG have two parametrs",
"MOD can't be a variable",
"Breake balance of MOD brackets",
"MOD have two parametrs",
"CEIL can't be a variable",
"Breake balance of CEIL brackets",
"FLOOR can't be a variable",
"Breake balance of FLOOR brackets",
"SECANT can't be a variable",
"Breake balance of SECANT brackets",
"COSECANT can't be a variable",
"Breake balance of COSECANT brackets",
"COTAN can't be a variable",
"Breake balance of COTAN brackets",
"ASEC can't be a variable",
"Breake balance of ASEC brackets",
"ACOSEC can't be a variable",
"Breake balance of ACOSEC brackets",
"ACOTAN can't be a variable",
"Breake balance of ACOTAN brackets",
"COSECH can't be a variable",
"Breake balance of COSECH brackets",
"COTANH can't be a variable",
"Breake balance of COTANH brackets",
"ASINH can't be a variable",
"Breake balance of ASINH brackets",
"ACOSH can't be a variable",
"Breake balance of ACOSH brackets",
"ATANH can't be a variable",
"Breake balance of ATANH brackets",
"ASECH can't be a variable",
"Breake balance of ASECH brackets",
"ACOSECH can't be a variable",
"Breake balance of ACOSECH brackets",
"ACOTANH can't be a variable",
"Breake balance of ACOTANH brackets",
"You can't chage constants"
};
cout << e[error] << endl;
}
template <class PType>
void CParser<PType>::get_token()
{
int i=0;
register char* temp;
char fun[10] = {0};
tok_type = 0;
temp = token;
*temp = '\0';
if( !*exp_ptr ) return;
while ( isspace(*exp_ptr) ) *exp_ptr++;
if ( strchr("+-*/%^=(),:;",*exp_ptr) )
{
*temp++ = *exp_ptr++;
tok_type = DELIMITER;
}
else if ( isalpha(*exp_ptr) )
{
while ( !isdelim(*exp_ptr) )
{
fun[i] = *exp_ptr;
*temp++ = *exp_ptr++;
i++;
}
if ( strcmp(fun,"sin") == 0)
{
tok_type = FUNCTION;
fun_type = SIN;
}
else if ( strcmp(fun,"cos") == 0)
{
tok_type = FUNCTION;
fun_type = COS;
}
else if ( strcmp(fun,"exp") == 0)
{
tok_type = FUNCTION;
fun_type = EXP;
}
else if ( strcmp(fun,"ln") == 0)
{
tok_type = FUNCTION;
fun_type = LN;
}
else if ( strcmp(fun,"log10") == 0)
{
tok_type = FUNCTION;
fun_type = LOG10;
}
else if ( strcmp(fun,"tan") == 0)
{
tok_type = FUNCTION;
fun_type = TAN;
}
else if ( strcmp(fun,"sqrt") == 0)
{
tok_type = FUNCTION;
fun_type = SQRT;
}
else if ( strcmp(fun,"abs") == 0)
{
tok_type = FUNCTION;
fun_type = FABS;
}
else if ( strcmp(fun,"asin") == 0)
{
tok_type = FUNCTION;
fun_type = ASIN;
}
else if ( strcmp(fun,"acos") == 0)
{
tok_type = FUNCTION;
fun_type = ACOS;
}
else if ( strcmp(fun,"atan") == 0)
{
tok_type = FUNCTION;
fun_type = ATAN;
}
else if ( strcmp(fun,"sinh") == 0)
{
tok_type = FUNCTION;
fun_type = SINH;
}
else if ( strcmp(fun,"cosh") == 0)
{
tok_type = FUNCTION;
fun_type = COSH;
}
else if ( strcmp(fun,"tanh") == 0)
{
tok_type = FUNCTION;
fun_type = TANH;
}
else if ( strcmp(fun,"fact") == 0)
{
tok_type = FUNCTION;
fun_type = FACT;
}
else if ( strcmp(fun,"log") == 0)
{
tok_type = FUNCTION;
fun_type = LOG;
}
else if ( strcmp(fun,"mod") == 0)
{
tok_type = FUNCTION;
fun_type = FMOD;
}
else if ( strcmp(fun,"ceil") == 0)
{
tok_type = FUNCTION;
fun_type = CEIL;
}
else if ( strcmp(fun,"floor") == 0)
{
tok_type = FUNCTION;
fun_type = FLOOR;
}
else if ( strcmp(fun,"secant") == 0)
{
tok_type = FUNCTION;
fun_type = SECANT;
}
else if ( strcmp(fun,"cosecant") == 0)
{
tok_type = FUNCTION;
fun_type = COSECANT;
}
else if ( strcmp(fun,"cotan") == 0)
{
tok_type = FUNCTION;
fun_type = COTAN;
}
else if ( strcmp(fun,"asec") == 0)
{
tok_type = FUNCTION;
fun_type = ASEC;
}
else if ( strcmp(fun,"acosec") == 0)
{
tok_type = FUNCTION;
fun_type = ACOSEC;
}
else if ( strcmp(fun,"acotan") == 0)
{
tok_type = FUNCTION;
fun_type = ACOTAN;
}
else if ( strcmp(fun,"cosech") == 0)
{
tok_type = FUNCTION;
fun_type = COSECH;
}
else if ( strcmp(fun,"cotanh") == 0)
{
tok_type = FUNCTION;
fun_type = COTANH;
}
else if ( strcmp(fun,"asinh") == 0)
{
tok_type = FUNCTION;
fun_type = ASINH;
}
else if ( strcmp(fun,"acosh") == 0)
{
tok_type = FUNCTION;
fun_type = ACOSH;
} else if ( strcmp(fun,"atanh") == 0)
{
tok_type = FUNCTION;
fun_type = ATANH;
}
else if ( strcmp(fun,"atanh") == 0)
{
tok_type = FUNCTION;
fun_type = ATANH;
}
else if ( strcmp(fun,"asech") == 0)
{
tok_type = FUNCTION;
fun_type = ASECH;
}
else if ( strcmp(fun,"acosech") == 0)
{
tok_type = FUNCTION;
fun_type = ACOSECH;
}
else if ( strcmp(fun,"acotanh") == 0)
{
tok_type = FUNCTION;
fun_type = ACOTANH;
}
else
{
cur_var = fun;
tok_type = VARIABLE;
}
}
else if ( isdigit(*exp_ptr) )
{
while ( !isdelim(*exp_ptr) ) *temp++ = *exp_ptr++;
tok_type = NUMBER;
}
*temp='\0';
}
template <class PType>
int CParser<PType>::isdelim(char c)
{
if ( strchr(" +-/*%^=(),;:",c) || c == 9 || c == '\r' || c == 0)
return 1;
return 0;
}
template <class PType>
PType CParser<PType>::find_var(string s)
{
tVr::iterator pos = vars.find(s);
if ( pos==vars.end() )
{
serror(3);
return (PType) 0;
}
return pos->second;
}
template <class PType>
bool CParser<PType>::IsError()
{
return IsErr;
}
template <class PType>
tVr CParser<PType>::GetVars()
{
return vars;
}
template <class PType>
void CParser<PType>::SetValue(string var,PType& value)
{
vars[var] = value;
}
template <class PType>
PType CParser<PType>::GetValue(string var)
{
return vars[var];
}
#endif
Вот как пользоваться:
Код: ![Выделить весь код](images/misc/selectcode.png)
#include "Parser.h"
int main()
{
char expstr[80];
CParser<double> cP;
for(;;)
{
cout << "Enter the expretions: "; cin.getline(expstr,80);
if(*expstr == '.') break;
cout << "Answer: " << setprecision(30) << cP.eval_exp(expstr) << "\n\n";
}
return 0;
}
|