C++ 一个简单的解释器 - 四则运算
2016-08-01 00:00
351 查看
#include <list> using namespace std; /* ───────────────────────────── │ 10 │ + │ 20 │ * | 5 | ───────────────────────────── (run interpret) ===>>> Token[Digits] : 10 Token[Operator] : + Token[Digits] : 20 Token[Operator] : * Token[Digits] : 5 ===>>> 10 + 20 * 5 优先级: x÷ > +- ===>>> 10 + 100 ===>>> 110 */ // // 配置 // const char CounterDigits[] = "1234567890"; const char CounterOperators[] = "*/+-"; const char CounterNils[] = " "; enum TokensTypes { Nil, Operator, Digits, Eof, Err }; // // common // inline bool isinchars( const char* str, char s ) { int len = strlen( str ); for( int i = 0; i < len; i++ ) if( s == str[i] ) return true; return false; } inline bool isDigit( char s ) { return isinchars( CounterDigits, s ); } inline bool isOperator( char s ) { return isinchars( CounterOperators, s ); } inline bool isNil( char s ) { return isinchars( CounterNils, s ); } // // 类实现 // class Token { public: Token( TokensTypes tts ) { this->type = tts; for( char &ch : raw ) ch = 0; } Token( TokensTypes tts, char* rawstr, int startpos, int endpos ) { this->type = tts; char tmpch = rawstr[endpos]; rawstr[endpos] = 0; strcpy( this->raw, rawstr + startpos ); rawstr[endpos] = tmpch; } TokensTypes type; char raw[11]; }; class CounterInterpreter { public: CounterInterpreter( char* linestr ) : rawstring( linestr ), pos( 0 ) {} ~CounterInterpreter() { tokens.clear(); } //每个Token分析 Token readtoken() { int startpos = this->pos; while( 1 ) { //空格时startpos和pos同时递增 if( isNil( rawstring[this->pos] ) ) { startpos = ++this->pos; continue; } //只有startpos处就是Operator时才判断为操作符 else if( isOperator( rawstring[startpos] ) ) { return Token( TokensTypes::Operator, rawstring, startpos, ++this->pos ); } //前方不是数字的数字处为Digits的结束处 else if( isDigit( rawstring[this->pos] ) ) { if( !isDigit( rawstring[this->pos + 1] ) ) return Token( TokensTypes::Digits, rawstring, startpos, ++this->pos ); } //EOF else if( rawstring[this->pos] == 0 ) { return Token( TokensTypes::Eof ); } //ERROR else { this->pos++; return Token( TokensTypes::Err ); } this->pos++; } } //Token分解 bool analysis() { while( 1 ) { Token t = readtoken(); tokens.push_back( t ); if( t.type == Eof ) break; if( t.type == Err ) return false; } return true; } //正确性验证 bool verify() { TokensTypes nextstatus = TokensTypes::Digits; for( auto t : tokens ) { //d+o+d if( t.type != nextstatus && t.type != TokensTypes::Eof ) return false; //数字可以放在最前最后 但操作符不行 if( t.type == TokensTypes::Eof && nextstatus == TokensTypes::Digits ) return false; if( nextstatus == TokensTypes::Digits ) nextstatus = TokensTypes::Operator; else if( nextstatus == TokensTypes::Operator ) nextstatus = TokensTypes::Digits; } return true; } //最终计算 int execute() { //优先计算*/ //遇到*/时,将自己+身边的2个Token进行重新计算后, //删除右边的2个,并将结果写入最左边Token for( auto t = tokens.begin(); t != tokens.end(); t++ ) { if( (*t).type == TokensTypes::Operator ) { if( (*t).raw[0] == '*' ) { t--; int tmp = strtol( (*t).raw, 0, 10 ); t++; t++; tmp *= strtol( (*t).raw, 0, 10 ); t--; t--; sprintf( (*t).raw, "%d", tmp ); t++; tokens.erase( t++ ); tokens.erase( t++ ); t--; } else if( (*t).raw[0] == '/' ) { t--; int tmp = strtol( (*t).raw, 0, 10 ); t++; t++; tmp /= strtol( (*t).raw, 0, 10 ); t--; t--; sprintf( (*t).raw, "%d", tmp ); t++; tokens.erase( t++ ); tokens.erase( t++ ); t--; } } } //最后得出总数:计算+- int total = 0; for( auto t = tokens.begin(); t != tokens.end(); t++ ) { if( (*t).type == TokensTypes::Digits ) { total = strtol( (*t).raw, 0, 10 ); } else if( (*t).type == TokensTypes::Operator ) { switch( (*t).raw[0] ) { case '+': t++; total += strtol( (*t).raw, 0, 10 ); break; case '-': t++; total -= strtol( (*t).raw, 0, 10 ); break; } } } return total; } //将token按顺序装起来 list tokens; char* rawstring; int pos; };
简单测试一下:
void main() { string str; while( 1 ) { //cin >> str; //bug: cin会处理空格为结束符 getline( cin, str ); CounterInterpreter ci( (char*)(str.data()) ); cout << "analysis : " << ci.analysis() << endl; cout << "verify : " << ci.verify() << endl; cout << "result : " << ci.execute() << endl; } }
相关文章推荐
- 学习C++的成果,一个简单的四则运算计算器内核
- 一个简单的四则运算源代码
- Redy语法分析--一个简单的四则运算计算器
- 一个简单的四则运算程序C语言实现--实现处理括号
- 利用栈ADT写了一个简单的四则混合运算
- 利用ANTLR4实现一个简单的四则运算计算器
- 自己写得C++简单的四则运算小程序
- 【Visual Basic】纯代码不拖控件,利用动态生成控件的方式完成一个简单的四则运算计算器
- C++第5周任务【任务2】本任务将设计一个简单的分数类,完成对分数的几个运算。一则巩固基于对象编程的方法,二则也为第10章做运算符重载等积累些感性认识。
- 一个简单的运算表达式解释器例子
- C++ 通过main()函数输入参数,实现简单的四则运算
- 用C++编写一个随机产生多个两位数四则运算式子的简单程序
- 用c++简单实现四则运算
- c++通过栈和递归函数实现简单四则运算以及括号的的计算器
- 一个简单的四则运算计算器
- C++ 四则运算表达式(简单的+-*/带括号) 栈
- C++中提供了多种基本的数据类型。实际上,这些远不能满足我们的需求,如复数(第10章的例子大多是处理虚数的),再如分数。本任务将设计一个简单的分数类,完成对分数的几个运算。一则巩固基于对象编程的方法,
- 一个简单的运算表达式解释器例子
- 一个简单的四则运算程序C语言实现--无法处理括号
- 对于c++来说,最简单的就是四则运算了,这里有一个四则运算的计算器