写好了,支持 +-*/,**是乘方,()也支持。可以使用变量,名字必须用字母开头,后续可以是数字和字母。可以使用函数调用,语法为 函数名 (参数列表),参数列表用","隔开。我给出的例子里面,有一个 sum 是使用可变参数的。请大家有什么意见/ bug 都告诉我。
代码:
#ifndef CPP_EVAL_H_0AF40410D697CB5483C80E2594B25CF0_20040721__
#define CPP_EVAL_H_0AF40410D697CB5483C80E2594B25CF0_20040721__
#include <cmath>
#include <map>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <cstdlib>
namespace cpp_eval
{
template< typename N >
N eval( const char* E );
template< typename N >
N eval( const char* E, const ::std::map< ::std::string, N >& V );
template< typename N, typename F >
N eval( const char* E, const ::std::map< ::std::string, N >& V, F& f );
class eval_exception: public ::std::logic_error
{
public:
eval_exception( const char* desc ): logic_error(desc)
{}
};
template< typename N >
class DF
{
public:
N operator()( const char*, const ::std::vector< N >& P )
{
throw eval_exception( "unexisting function called" );
// return N();
}
};
template< typename N >
N eval( const char* E )
{
::std::map< ::std::string, N > V;
DF< N > f;
return eval( E, V, f );
}
template< typename N >
N eval( const char* E, const ::std::map< ::std::string, N >& V )
{
DF< N > f;
return eval( E, V, f );
}
template< typename N, typename F >
class evaler
{
const ::std::map< ::std::string, N >& MV;
F& MF;
const char* MC;
enum TT
{
AP = '+',
SN = '-',
MU = '*',
DI = '/',
PO = '~',
LB = '(',
RB = ')',
PS = ',',
I = 257,
U = 258,
FI = 259
};
TT MTT;
std::string MI;
N MVA;
void L()
{
for(;;)
{
if( isspace( *MC ) )
{
++MC;
continue;
}
else if( *MC == '*' && *( MC + 1 ) == '*' )
MTT = PO, MC += 2;
else if( *MC == AP || *MC == SN ||
*MC == MU || *MC == DI ||
*MC == LB || *MC == RB ||
*MC == PS )
MTT = ( TT )*MC, ++MC;
else if( isalpha( *MC ) )
{
MTT = I;
MI.clear();
MI += *MC;
++MC;
while( isalpha( *MC ) || isdigit( *MC ) )
MI += *MC, ++MC;
}
else if( *MC == 0)
MTT = FI;
else
{
MTT = U;
istringstream iss( MC );
iss >> MVA;
if( ! iss )
throw eval_exception( "error in format" );
MC += iss.rdbuf()->pubseekoff( 0, ios::cur, ios::in );
}
break;
}
}
void M( TT TT )
{
if( MTT == TT )
L();
else
throw eval_exception( "unmatched token" );
}
N E()
{
N R = ER( HR() );
return R;
}
N ER( const N& L )
{
N R = L;
if( MTT == AP )
M( AP ), R = ER( L + HR() );
else if( MTT == SN )
M( SN ), R = ER( L - HR() );
return R;
}
N HR()
{
return HER( SE() );
}
N HER( const N& L )
{
N R = L;
if( MTT == MU )
M( MU ), R = HER( L * SE() );
else if( MTT == DI )
M( DI ), R = HER( L / SE() );
return R;
}
N SE()
{
N R;
if( MTT == AP )
M( AP ), R = SE();
else if( MTT == SN )
M( SN ), R = - SE();
else
R = PE();
return R;
}
N PE()
{
N R = FA();
if( MTT == PO )
M( PO ), R = std::pow( R, static_cast< int >( PE() ) );
return R;
}
N FA()
{
N R;
if( MTT == U )
R = MVA, M( U );
else if( MTT == LB )
M( LB ), R = E(), M( RB );
else
R = LS();
return R;
}
N LS()
{
std::string id = MI;
M( I );
return LT( id );
}
N LT( const std::string& id )
{
N R;
if( MTT == LB )
{
M( LB );
std::vector< N > P = PL();
R = MF( id.c_str(), P );
}
else
{
if( MV.find( id ) == MV.end() )
throw eval_exception( "cannot find variable" );
R = MV.find( id )->second;
}
return R;
}
std::vector< N > PL()
{
std::vector< N > R;
for(;;)
{
if( MTT == RB )
{
M( RB );
break;
}
R.push_back( E() );
PT( R );
}
return R;
}
void PT( std::vector< N >& P )
{
if( MTT == PS )
M( PS ), P.push_back( E() ), PT( P );
}
public:
evaler( const ::std::map< ::std::string, N >& V, F& f )
: MV( V ), MF( f )
{}
N operator()( const char* expr )
{
MC = expr;
L();
N R = E();
if( MTT != FI )
throw eval_exception( "unexpect expression format" );
return R;
}
};
template< typename N, typename F >
N eval( const char* E, const ::std::map< ::std::string, N >& V, F& f )
{
return evaler< N, F >( V, f )( E );
}
};
#endif//CPP_EVAL_H_0AF40410D697CB5483C80E2594B25CF0_20040721__
代码:
#include "CppEval.h"
#include <iostream>
#include <numeric>
using namespace std;
class functions
{
public:
int operator()( const char* name, const ::std::vector< int >& params )
{
if( stricmp( name, "return1" ) == 0 )
{
if( params.size() != 0 )
throw 1;
return 1;
}
else if( stricmp( name, "negative" ) == 0 )
{
if( params.size() != 1 )
throw 1;
return - params[ 0 ];
}
else if( stricmp( name, "sum" ) == 0 )
{
return accumulate( params.begin(), params.end(), 0 );
}
}
};
int main()
{
map< string, int > variables;
variables[ "aa" ] = 100;
variables[ "b" ] = 200;
functions f;
cout<<cpp_eval::eval< int >( " + aa * aa / b - b / -2 /2/2 -- 5 ** 2 + -100 "
" + ( aa * aa / b - b / -2 /2/2 -- 5 ** 2 + -100 )"
" + return1() + negative( 1 ) + sum( 1, 2, 3, sum( 1 + 2 *5-7, 555, 111 ) )", variables, f )<<endl;
return 0;
}