FunctionTable实现
在Calc中要增加新的成员变量FunctionTable 记得初始化的顺序,让符号表先初始化 然后再初始化函数表 最后初始化存储表
Calc.cpp
让表达式计算器支持函数运算
对于一个好的科学计算器,内置函数是必需的。计算器必须能计算平方根、对数、三角函数等等。因而我们要让解析器识别这些函数,并调用适当的数学库函数。
FunctionTable实现
FunctionTable.h:
#ifndef _FUNCTION_TABLE_H_
#define _FUNCTION_TABLE_H_
class SymbolTable;
typedef double (*PtrFun)(double);
class FunctionTable
{
public:
FunctionTable(SymbolTable& tbl);
~FunctionTable();
void Init(SymbolTable& tbl);
unsigned int Size() const
{
return size_;
}
PtrFun GetFunction(unsigned int id) const
{
return pFuns_[id];
}
private:
PtrFun* pFuns_;
unsigned int size_;
};
#endif // _FUNCTION_TABLE_H_
FunctionTable.cpp:
#include "FunctionTable.h"
#include "SymbolTable.h"
#include <cmath>
#include <cassert>
#include <iostream>
struct FunctionEntry
{
PtrFun pFun_;
char* funName_;
};
FunctionEntry Entrys[] =
{
log, "log",
log10, "log10",
exp, "exp",
sqrt, "sqrt",
sin, "sin",
cos, "cos",
tan, "tan",
sinh, "sinh",
cosh, "cosh",
tanh, "tanh",
asin, "asin",
acos, "acos",
atan, "atan"
};
FunctionTable::FunctionTable(SymbolTable& tbl)
: size_(sizeof(Entrys) / sizeof(Entrys[0]))
{
Init(tbl);
}
void FunctionTable::Init(SymbolTable& tbl)
{
std::cout<<"function list:"<<std::endl;
pFuns_ = new PtrFun[size_];
for (unsigned int i=0; i<size_; ++i)
{
pFuns_[i] = Entrys[i].pFun_;
unsigned int j = tbl.Add(Entrys[i].funName_);
assert(i == j);
std::cout<<Entrys[i].funName_<<std::endl;
}
}
FunctionTable::~FunctionTable()
{
delete[] pFuns_;
}
在Calc中要增加新的成员变量FunctionTable 记得初始化的顺序,让符号表先初始化 然后再初始化函数表 最后初始化存储表
Calc.h:
#ifndef _CALC_H_
#define _CALC_H_
#include "SymbolTable.h"
#include "Storage.h"
#include "FunctionTable.h"
#include <string>
class Parser;
class Calc
{
friend class Parser;
public:
Calc() : funTbl_(symTbl_), storage_(symTbl_) {}
private:
Storage& GetStorage()
{
return storage_;
}
PtrFun GetFunction(unsigned int id) const
{
return funTbl_.GetFunction(id);
}
bool IsFunction(unsigned int id) const
{
return id < funTbl_.Size();
}
unsigned int AddSymbol(const std::string& str);
unsigned int FindSymbol(const std::string& str) const;
SymbolTable symTbl_;
FunctionTable funTbl_;
Storage storage_;
};
#endif // _CALC_H_
Calc.cpp
#include "Calc.h"
unsigned int Calc::FindSymbol(const std::string& str) const
{
return symTbl_.Find(str);
}
unsigned int Calc::AddSymbol(const std::string& str)
{
return symTbl_.Add(str);
}
在Node.h中要多增加一个一元运算节点
class FunctionNode : public UnaryNode
{
public:
FunctionNode(Node* child, PtrFun pFun)
: UnaryNode(child), pFun_(pFun) {}
double Calc() const;
private:
PtrFun pFun_;
};
Node.cpp
double FunctionNode::Calc() const
{
return (*pFun_)(child_->Calc());
}
if (scanner_.Token() == TOKEN_LPARENTHESIS) // function call
{
scanner_.Accept(); // accept '('
node = Expr();
if (scanner_.Token() == TOKEN_RPARENTHESIS)
{
scanner_.Accept(); // accept ')'
if (id != SymbolTable::IDNOTFOUND && calc_.IsFunction(id))
{
node = new FunctionNode(node, calc_.GetFunction(id));
}
else
{
status_ = STATUS_ERROR;
std::cout<<"Unknown function "<<"\""<<symbol<<"\""<<std::endl;
}
}
else
{
status_ = STATUS_ERROR;
std::cout<<"Missing parenthesis in a function call."<<std::endl;
}
}
else
{
if (id == SymbolTable::IDNOTFOUND)
{
id = calc_.AddSymbol(symbol);
}
node = new VariableNode(id, calc_.GetStorage());
}