C++ Programming Language 4th中的Calculator源代码整理,因为在C++ Programming Language中,涉及了很多文件位置之类的变化,所以,这里只是其中的一个版本:

error.h

#include <string>
#include <iostream> namespace Error
{
extern int no_of_errors; inline double error(const std::string& s)
{
no_of_errors++;
std::cerr << "error:" << s << '\n';
return ;
}
}

Table.h

#include <map>
#include <string> namespace Table
{
extern std::map<std::string, double> table;
}

Lexer.h

#include <string>
#include <istream> namespace Lexer
{
enum class Kind : char
{
name,
number,
end,
plus='+',
minus='-',
mul='*',
div='/',
print=';',
assign='=',
lp='(',
rp=')'
}; struct Token
{
Kind kind;
std::string string_value;
double number_value;
}; class Token_stream
{
public:
Token_stream(std::istream& s) : ip{&s}, owns(false) { }
Token_stream(std::istream* p) : ip(p), owns{ true } { } ~Token_stream() { close(); } Token get(); // read and return next token
Token& current() // most recent read token
{
return ct;
} void set_input(std::istream& s) { close(); ip = &s; owns = false; }
void set_input(std::istream* p) { close(); ip = p; owns = true; } private:
void close() { if (owns) delete ip; } std::istream* ip; // pointer to an input stream
bool owns; // does the Token_stream own the istream?
Token ct{ Kind::end }; // current token
}; extern Token_stream ts;
}

Parser.h

namespace Parser
{
double prim(bool get);
double term(bool get);
double expr(bool get);
}

Driver.h

#include <iostream>
#include "Lexer.h"
#include "Parser.h" namespace Driver
{
using namespace Lexer;
using namespace Parser; inline void calculate()
{
for (;;)
{
ts.get();
if (ts.current().kind == Kind::end) break;
if (ts.current().kind == Kind::print) continue;
std::cout << expr(false) << "\n";
}
}
}

Error.cpp

#include "Error.h"

namespace Error
{
int no_of_errors = ;
}

Table.cpp

#include "Table.h"

namespace Table
{
std::map<std::string, double> table;
}

Lexer.cpp

#include "Lexer.h"
#include <iostream> namespace Lexer
{
Token Token_stream::get()
{
char ch = ; do { // skip whitespace except '\n'
if (!ip->get(ch))
return ct = { Kind::end };
} while (ch != '\n' && isspace(ch)); switch (ch)
{
case :
return ct = { Kind::end }; // assign and return
case ';': // end of expression; print
case '\n':
return ct = { Kind::print };
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return ct = {static_cast<Kind>(ch)};
case '':case '':case '':case '':case '':case '':case '':case '':case '':case '':
case '.':
ip->putback(ch); // put the first digit (or .) back into the input stream
*ip >> ct.number_value; // read number into ct
ct.kind = Kind::number;
return ct;
default: // name, name = , or error
if (isalpha(ch))
{
ct.string_value = ch;
while (ip->get(ch) && isalnum(ch))
ct.string_value += ch; // append ch to end of string_value
ip->putback(ch);
return ct = { Kind::name };
} }
} Token_stream ts{ std::cin };
}

Parser.cpp

#include "Parser.h"
#include "Lexer.h"
#include "Error.h"
#include "Table.h" namespace Parser
{
using namespace Lexer;
using namespace Error;
using namespace Table; double expr(bool get) // add and subtract
{
double left = term(get); for (;;)
{
switch (ts.current().kind)
{
case Kind::plus:
left += term(true);
break;
case Kind::minus:
left -= term(true);
break;
default:
return left;
}
}
} double term(bool get) // multiply and divide
{
double left = prim(get); for (;;)
{
switch (ts.current().kind)
{
case Kind::mul:
left *= prim(true);
break;
case Kind::div:
if (auto d = prim(true))
{
left /= d;
break;
}
return error("divide by 0");
default:
return left;
}
}
} double prim(bool get) // handle primaries
{
if (get) ts.get(); // read next token switch (ts.current().kind)
{
case Kind::number: // floating-point constant
{
double v = ts.current().number_value;
ts.get();
return v;
}
case Kind::name:
{
double& v = table[Lexer::ts.current().string_value]; // find the corresponding
if (ts.get().kind == Kind::assign)
v = expr(true); // '=' seen: assignment
return v;
}
case Kind::minus: // unary minus
return -prim(true);
case Kind::lp:
{
auto e = expr(true);
if (ts.current().kind != Kind::rp)
return error("')' expected");
ts.get(); // eat ')'
return e;
}
default:
return error("primary expected");
}
}
}

实际使用代码(测试代码):

#include "Error.h"
#include "Driver.h"
#include "Table.h" int main()
{
Table::table["pi"] = 3.1415926535897932385; // inser t predefined names
Table::table["e"] = 2.7182818284590452354; Driver::calculate();
return Error::no_of_errors;
}

C++ Programming Language中的Calculator源代码的更多相关文章

  1. C++ Programming Language中的narrow_cast实现

    在C++中,各种数值类型的转化是C++编译过程中警告的主要来源,但是,很多时候,我们需要使用各种数值类型,例如我们用数组的某一位表示大小为对应序号的值,这种情况下,经常会涉及多种数值类型.根据C++ ...

  2. 编程提取字符串"Java is a programming language"中的各个单词,并打印输出。

    import java.lang.String; import java.util.StringTokenizer; public class StringGetWord{ /* 编程提取字符串&qu ...

  3. the C programming language 阅读笔记1

    读了一遍著名的<the C programming language>,果然如听说的一样,讲解基础透彻,案例简单典型,确实自己C语言还有很多细节点不是很清楚. 总结一下阅读的收获(部分原书 ...

  4. Introduction to OOC Programming Language

    Introduction to OOC Programming Language 文/akisann @ cnblogs.com / zhaihj @ github.com 本文同时发布在github ...

  5. iOS Swift-元组tuples(The Swift Programming Language)

    iOS Swift-元组tuples(The Swift Programming Language) 什么是元组? 元组(tuples)是把多个值组合成一个复合值,元组内的值可以使任意类型,并不要求是 ...

  6. iOS Swift-控制流(The Swift Programming Language)

    iOS Swift-控制流(The Swift Programming Language) for-in 在Swift中for循环我们可以省略传统oc笨拙的条件和循环变量的括号,但是语句体的大括号使我 ...

  7. The Swift Programming Language 中文翻译版(个人翻新随时跟新)

    The Swift Programming Language --lkvt 本人在2014年6月3日(北京时间)凌晨起来通过网络观看2014年WWDC 苹果公司的发布会有iOS8以及OS X 10.1 ...

  8. [iOS翻译]《The Swift Programming Language》系列:Welcome to Swift-01

    注:CocoaChina翻译小组已着手此书及相关资料的翻译,楼主也加入了,多人协作后的完整译本将很快让大家看到. 翻译群:291864979,想加入的同学请进此群哦.(本系列不再更新,但协作翻译的进度 ...

  9. 不忘初心 --- 重读<<The C Programming Language>>

    这篇文章应该发布在好几年前,2011年计算机界大师Dennis Ritchie仙逝,那时对大师的映象还停留在大一刚学编程时:Unix的合作开发者,C语言的发明人.通过网上的纪念文章<<Un ...

随机推荐

  1. PS学习之小猪佩奇身上纹,掌声送给社会人

    首先准备素材 用ps首先打开素材一 首先对图片去色 快捷键:shift+Ctrl+u 调整色阶 设置高斯模糊: 另存为psd格式,命名为叠加的对象 再次打开素材一,把佩奇拖入到图层里,并调整大小,旋转 ...

  2. 树莓派ssh服务

    从官网下载的镜像更新raspberry pi 3 B,但默认是不支持SSH的,即不可外部通过SSH登陆到板子里. 解决办法很简单,在SD卡的根目录下创建一个"ssh"的文件夹即可.

  3. Mybatis(二,三)

    参考孤傲苍狼的博客,地址如下: http://www.cnblogs.com/xdp-gacl/p/4264301.html 在此声明,自己写博客,是为了学习总结过程中的记录.没有侵权和偷懒的意思. ...

  4. $trainClassLayer.find('input[name=data-item-checkbox]').eq(index).change();//激活第index+1那个checkbox

    ☆ $.each(data, function (index, org) { if (org.alreadySent) { $trainClassLayer.find('input[name=data ...

  5. python数据类型及字符编码

    一.python数据类型,按特征划分 1.数字类型 整型:布尔型(True,False).长整型(L),会自动帮你转换成长整型.标准整型 2.序列类型 字符串(str).元组(tuple).列表(li ...

  6. struts2(三)拦截器

    拦截器 需求 如果要访问某一个action类中的某一个方法的内容,如果是admin用户,则访问,如果不是admin用户,则不能访问. 实现 缺点  权限判断的代码和业务逻辑代码混合在一起了 利用拦截器 ...

  7. centos7 部署elasticsearch

    环境: 系统:centos7.3 版本:elasticsearch6.2.3 head版本:https://codeload.github.com/mobz/elasticsearch-head/zi ...

  8. ipfs docker 运行试用

    ipfs 是一个分布式,p2p 的文件系统,参考了git.bt.sfs 以及web 的设计 环境准备 docker-compose 文件 version: "3" services ...

  9. openresty 使用lua-resty-shell 执行shell 脚本

    lua-resty-shell 是一个很不错的项目,让我们可以无阻塞的执行shell命令,之间的通信 是通过socket (一般是unix socket) 环境准备 docker-compose 文件 ...

  10. lch 儿童围棋课堂 初级篇1 ( (李昌镐 著))

    第1章 常用术语 第2章 吃子 第3章 死活:死活题初步 第4章 劫争 第5章 中盘 第6章 官子 第7章 形势判断 第8章 对杀技巧 第9章 手筋 第1章 常用术语 一 镇 在对方棋子上方隔一路落下 ...