計算器的github下載地址:https://github.com/ljian1992/calculator
有了構建語法的類,存儲符號的類,現在就可以對表達式進行掃描,解析了。掃描可以抽象出一個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(); //根據解析到的命令執行命令
};