利用解析原理写一个简单的计算器
2016-11-18 09:39
309 查看
计算器在计算机诞生之前便已经产生,计算在人类远古时期就已经开始。
利用的是语法解析的思想,参考programming_principles_and_practice_using_c++_2nd_ed
grammer:
expression:
term;
expression + term;
expression - term;
term:
primary;
term * primary;
term / primary;
primary:
number;
'(' expression ')'
命名一个Token类,表示最小单位,比如*, 3.14, (,以及一个Token_stream类,stream中获取一个Token,或者把Token放入到stream中。
此类程序非常容易拓展,比如需要加上%运算符,可以在term上加上语法, term % primary.
利用的是语法解析的思想,参考programming_principles_and_practice_using_c++_2nd_ed
grammer:
expression:
term;
expression + term;
expression - term;
term:
primary;
term * primary;
term / primary;
primary:
number;
'(' expression ')'
命名一个Token类,表示最小单位,比如*, 3.14, (,以及一个Token_stream类,stream中获取一个Token,或者把Token放入到stream中。
此类程序非常容易拓展,比如需要加上%运算符,可以在term上加上语法, term % primary.
#include "std_lib_facilities.h" struct Token { char kind; double value; string name; Token(char ch) :kind(ch), value(0) { } Token(char ch, double val) :kind(ch), value(val) { } }; class Token_stream { bool full; Token buffer; public: Token_stream() :full(0), buffer(0) { } Token get(); void unget(Token t) { buffer=t; full=true; } void ignore(char); }; const char let = 'L'; const char quit = 'Q'; const char print = ';'; const char number = '8'; const char name = 'a'; Token Token_stream::get() { if (full) { full=false; return buffer; } char ch; cin >> ch; switch (ch) { case '(': case ')': case '+': case '-': case '*': case '/': case '%': case ';': case '=': return Token(ch); case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { cin.unget(); double val; cin >> val; return Token(number,val); } default: if (isalpha(ch)) { string s; s += ch; while(cin.get(ch) && (isalpha(ch) || isdigit(ch))) s += ch; cin.unget(); if (s == "let") return Token(let); if (s == "quit") return Token(quit); return Token(name); } error("Bad token"); } } void Token_stream::ignore(char c) { if (full && c==buffer.kind) { full = false; return; } full = false; char ch; while (cin>>ch) if (ch==c) return; } struct Variable { string name; double value; Variable(string n, double v) :name(n), value(v) { } }; vector<Variable> names; double get_value(string s) { for (int i = 0; i<names.size(); ++i) if (names[i].name == s) return names[i].value; error("get: undefined name ",s); } void set_value(string s, double d) { for (int i = 0; i<=names.size(); ++i) if (names[i].name == s) { names[i].value = d; return; } error("set: undefined name ",s); } bool is_declared(string s) { for (int i = 0; i<names.size(); ++i) if (names[i].name == s) return true; return false; } Token_stream ts; double expression(); double primary() { Token t = ts.get(); switch (t.kind) { case '(': { double d = expression(); t = ts.get(); if (t.kind != ')') error("'(' expected"); } case '-': return - primary(); case number: return t.value; case name: return get_value(t.name); default: error("primary expected"); } } double term() { double left = primary(); while(true) { Token t = ts.get(); switch(t.kind) { case '*': left *= primary(); break; case '/': { double d = primary(); if (d == 0) error("divide by zero"); left /= d; break; } default: ts.unget(t); return left; } } } double expression() { double left = term(); while(true) { Token t = ts.get(); switch(t.kind) { case '+': left += term(); break; case '-': left -= term(); break; default: ts.unget(t); return left; } } } double declaration() { Token t = ts.get(); if (t.kind != 'a') error ("name expected in declaration"); string name = t.name; if (is_declared(name)) error(name, " declared twice"); Token t2 = ts.get(); if (t2.kind != '=') error("= missing in declaration of " ,name); double d = expression(); names.push_back(Variable(name,d)); return d; } double statement() { Token t = ts.get(); switch(t.kind) { case let: return declaration(); default: ts.unget(t); return expression(); } } void clean_up_mess() { ts.ignore(print); } const string prompt = "> "; const string result = "= "; vo 4000 id calculate() { while(true) try { cout << prompt; Token t = ts.get(); while (t.kind == print) t=ts.get(); if (t.kind == quit) return; ts.unget(t); cout << result << statement() << endl; } catch(runtime_error& e) { cerr << e.what() << endl; clean_up_mess(); } } int main() try { calculate(); return 0; } catch (exception& e) { cerr << "exception: " << e.what() << endl; char c; while (cin >>c&& c!=';') ; return 1; } catch (...) { cerr << "exception\n"; char c; while (cin>>c && c!=';'); return 2; }
相关文章推荐
- Skinned Mesh原理解析和一个最简单的实现示例
- 利用java做一个简单的计算器
- Skinned Mesh 原理解析和一个最简单的实现示例
- 利用javascript写一个简单的计算器
- 【学习中的分享】 iOS利用UILabel和UIButton制作一个简单的计算器
- Skinned Mesh原理解析和一个最简单的实现示例
- Skinned Mesh原理解析和一个最简单的实现示例
- 【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
- unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
- 【Visual Basic】纯代码不拖控件,利用动态生成控件的方式完成一个简单的四则运算计算器
- Skinned Mesh 原理解析和一个最简单的实现示例
- Skinned Mesh原理解析和一个最简单的实现示例
- 利用JAVA的动态属性之反射原理实现一个简单AOP容器 - AOP的实现原理分析
- Skinned Mesh原理解析和一个最简单的实现示例
- 利用java做一个简单的计算器
- Skinned Mesh 原理解析和一个最简单的实现示例
- 转载-Skinned Mesh原理解析和一个最简单的实现示例 .
- 【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
- Skinned Mesh原理解析和一个最简单的实现示例 .
- 射线的原理用法以及一个利用射线实现简单拾取的小例子