表达式计算器类的设计3(面向对象的表达式计算器6)

概述

有了构建语法的类,存储符号的类,现在就可以对表达式进行扫描,解析了。扫描可以抽象出一个Scanner类来完成这一个功能,而解析可以抽象出一个Parser类来完成这一个功能。这两个类存在一定的关系,扫描与解析的互动是这样子的:扫描到一个标识符,然后解析它是什么标识符。由于该表达式计算器是要支持一些命令的,命令的解析和表达式的解析过程完全不一样,所有呢,又要设置一个CommandParser类,来解析命令。

Scanner类,Parser类,CommandParser类的设计

Scanner类

enum EToken {
    TOKEN_COMMAND,
    TOKEN_ERROR,
    TOKEN_END,
    TOKEN_NUMBER,
    TOKEN_IDENTIFIER,
    TOKEN_PLUS,
    TOKEN_MINUS,
    TOKEN_MUTIPLY,
    TOKEN_DIVIDE,
    TOKEN_LPARENTHESIS,
    TOKEN_RPARENTHESIS,
    TOKEN_ASSIGN,
};   class Scanner
{
private:
    std::istream& in_;                 //标准输入流
    bool isEmpty_;                     //是否为空
    EToken token_;                     //记录扫描结果
    double number_;                    //扫描到的数字
    std::string symbol_;               //扫描到标识符
    int look_;                         //扫描到的字符
    void ReadChar();                   //从标准输入流中读取字符
  public:
    explicit Scanner(std::istream& in);
    void Accept();                     //扫描一个标识符or操作数or操作数
    void AcceptCommand();              //扫描命令
    void CleanIstream();               //清除标准输入流缓存
    double Number() const;             //获取扫描到的数字
    bool IsEmpty()const;               //判断是否为空
    bool IsDone() const;               //判断是否扫描完毕
    bool IsCommand() const;            //判断是否是命令
    std::string GetSymbol() const;     //获取扫描到的标识符
    EToken Token() const;              //获取扫描结果

};

Parser类

enum STATUS
{
    STATUS_OK,
    STATUS_ERROR,
    STATUS_QUIT,
};     class Parser
{
private:
    Scanner& scanner_;
    std::auto_ptr<Node> tree_;           //表达式语法树
    STATUS status_;                      //状态
    Calc &calc_;                         //要处理的符号信息
  public:
    Parser(Scanner& scanner, Calc& calc);   /*与scanner类相关联*/
    ~Parser();
    STATUS Parse();                         //解析一个表达式生成表达式树
    std::auto_ptr<Node> Expr();             //解析表达式
    std::auto_ptr<Node> Term();             //解析项
    std::auto_ptr<Node> Factor();           //解析因子
    double Calculate() const;               //计算出表达式的值
  };

CommandParser类

class CommandParser
{
private:
    enum Ecommand   //由于该宏只会在CommandParser类内部用到,故定义在内部
    {
        CMD_HELP,
        CMD_QUIT,
        CMD_VAR,
        CMD_FUN,
        CMD_LOAD,
        CMD_SAVE,
        CMD_ERROR,
    };
private:
    Scanner& scanner_;
    Calc &calc_;
    ECommand cmd_;                           //解析到的命令
    std::string cmdName_;                    //命令名
  void Help() const;                       //帮助命令
    void ListVar() const;                    //打印出变量表
    void ListFun() const;                    //打印出函数表
    STATUS Load(const std::string& fileName);//从文件中加载内容到变量表和函数表中
    STATUS Save(const std::string& fileName);//存储变量表和函数表到文件中
  public:
    CommandParser(Scanner& scanner, Calc& calc_);   /*与scanner类相关联*/
    STATUS Execute();                         //根据解析到的命令执行命令   

};
时间: 2024-12-15 06:59:38

表达式计算器类的设计3(面向对象的表达式计算器6)的相关文章

表达式计算器类的设计5(面向对象的表达式计算器8)

计算器的github下载地址:https://github.com/ljian1992/calculator 概述 表达式计算器的类基本已经设计完成了,由于在程序运行的时候总会有这样那样的异常,例如:a +2, a没有初始化,对于异常的管理一般而言是需要自定义异常类.这个自定义异常类也是在继承了系统已经定义好的exception类,然后再重新定义内容. 异常的种类 语法异常---->SyntaxError类 赋值时左操作数不是变量:1 = 2; 缺少括号:1 + (2*2 不认识的函数: 函数缺

表达式计算器类的设计4(面向对象的表达式计算器7)

概述 把符号表和变量表中的内容保存到一个文件中,通过IO文件流,来把符号表和变量表存储到文件中.在这之前需要弄明白什么是序列化和反序列化 对象的序列化 序列化:把对象转换为字节序列的过程 反序列化:把字节序列恢复为对象的过程 我们要把SymbolTable类的对象(符号表)和Storage类的对象(变量表)转换成字节序列保存到文件中,这时就可以设置Serializer类来完成这样的功能,同样的设置一个DeSerializer类来完成把保存到文件当中的字节序列恢复为对象的功能.这里要注意的是,所有

表达式计算器类的设计1(表达式计算器4)

计算器的github下载地址:https://github.com/ljian1992/calculator 我们的最终目的是计算出表达式中的值,因此就需要定义一个抽象类用于计算表达式的值,该抽象类定义为:Node 下面所有的类图不使用UML建模语言画的,是通过visual studio自动生成的类关系图(自己用UML建模画的不小心被我删掉了) Node的类图 它继承了个Noncpyable类,由于我们是要做面向对象的表达式计算器,所以呢,通过一个小小的手段,把拷贝给禁止掉.这个小小的手段就是让

表达式计算器类的设计2(表达式计算器5)

计算器的github下载地址:https://github.com/ljian1992/calculator 符号表,函数表,变量存储表 表达式计算器,需要支持变量和函数,而变量和函数都是些符号,因此设置一个SymbolTable类来存储这些符号.符号有两种,一种是变量,一种是函数,故在设置一个Storage类存储变量中的值,设置一个FunctionTable类来存储函数.由于这三中类存在着联系,现在在设置一个Calc类来管理它们. SymbolTable类,FunctionTable类,Sto

iOS类的合理设计,面向对象思想

每天更新的东西可能有反复的内容.当时每一部分的知识点是不同的,须要大家认真阅读 这里介绍了iOS类的合理设计.面向对象思想 main.m #import <Foundation/Foundation.h> #import "Iphone.h" int main(int argc, const char * argv[]) { Iphone * phone = [Iphone new]; phone->_color = IphoneColorWhite; phone-&

表达式的语法解析(面向对象的表达式计算器2)

巴科斯范式(BNF) 1.在双引号中的字("word")代表着这些字符本身.而double_quote用来代表双引号. 2.在双引号外的字(有可能有下划线)代表着语法部分. 3.尖括号( < > )内包含的为必选项. 4.方括号( [ ] )内包含的为可选项. 5.大括号( { } )内包含的为可重复0至无数次的项. 6.竖线( | )表示在其左右两边任选一项,相当于"OR"的意思. 7.::= 是“被定义为”的意思. 表达式的BNF表示 一个表达式分解

黑 马 程 序 员_视频学习总结&lt;Objective-C&gt;----01 面向对象思想、类和对象、面向对象方法

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.面向对象 1. 面向对象和面向过程思想区别 OC为面向对象.C为面向过程.实质是解决问题的两种不同的思想.面向过程关注的是步骤,面向对象关注的是解决问题需要的对象. 2. 常用术语 面向过程:Procedure Oriented面向对象:Object Oriented 简称OO面向对象编程:Object OrientedProgrammin

C++primer笔记2:变量和基本类型、字符串,向量和数组、表达式、类

第2章:变量和基本类型 char 8位 bool 未定义 short 短整型16 int 整型16 long 长整型32 long long 长整型64 C++11新定义的 float: 1个字 32位 6位有效位 double: 2个字 64位 10位有效位 long double: 10位有效位 带符号和不带符号的 unsigned 不带符号 仅仅表示大于0的 signed 带符号 大于,小于,0 基本字符集 :比特位 可寻址的最小内存块:字节 8比特 存储的基本单位 :字 32或64比特

Python 类的设计原则

# 面向对象遵循的原则: SOLID # S(Single Responsibility Principle) # 单一职责原则 # 一个类只负责一项职责 # 好处 # 易于维护, 写出高内聚的代码 # 易于代码复用 # 案例 # 我们之前写的计算器类 # 假设只包含加减乘除运算和结果打印 # 如果往后需要增加, 结果写入文件, 结果参与其他运算, 结果上传服务器... # 是不是每一次都需要去修改此类? 就导致这个类变得特别臃肿; 不利于维护和部分代码复用 # 解决方案 # 计算器只包含, 加