面向物件計算器(五)
阿新 • • 發佈:2018-12-29
主要是為了更正之前的設計缺陷
1、算術表示式解析器的一個缺陷在於它的語法是右結合的。這意味著8-2+1被解析為8-(2+1)
2、可以通過更正語法
expresion := expresion ’+’ term
但這會導致無限迴圈(Expr呼叫Expr,Expr又呼叫Expr…)
3、一種解決方法:
更改後的類圖:
在程式中的具體實現為:
Node.h:
Node.cppclass MultipleNode : public Node { public: MultipleNode(Node* node) { AppendChild(node, true); } void AppendChild(Node* node, bool positive) { childs_.push_back(node); positives_.push_back(positive); } ~MultipleNode(); protected: std::vector<Node*> childs_; std::vector<bool> positives_; }; class SumNode : public MultipleNode { public: SumNode(Node* node) : MultipleNode(node) {} double Calc() const; }; class ProductNode : public MultipleNode { public: ProductNode(Node* node) : MultipleNode(node) {} double Calc() const; };
MultipleNode::~MultipleNode() { std::vector<Node*>::const_iterator it; for (it = childs_.begin(); it != childs_.end(); ++it) { delete *it; } } double SumNode::Calc() const { double result = 0.0; std::vector<Node*>::const_iterator childIt = childs_.begin(); std::vector<bool>::const_iterator positiveIt = positives_.begin(); for (; childIt != childs_.end(); ++childIt, ++positiveIt) { assert(positiveIt != positives_.end()); double val = (*childIt)->Calc(); if (*positiveIt) result += val; else result -= val; } assert(positiveIt == positives_.end()); return result; } double ProductNode::Calc() const { double result = 1.0; std::vector<Node*>::const_iterator childIt = childs_.begin(); std::vector<bool>::const_iterator positiveIt = positives_.begin(); for (; childIt != childs_.end(); ++childIt, ++positiveIt) { assert(positiveIt != positives_.end()); double val = (*childIt)->Calc(); if (*positiveIt) result *= val; else if (val != 0.0) result /= val; else { std::cout<<"Division by zero."<<std::endl; return HUGE_VAL; } } assert(positiveIt == positives_.end()); return result; }
Parser.cpp:
Node* Parser::Expr() { Node* node = Term(); EToken token = scanner_.Token(); //if (token == TOKEN_PLUS) //{ // scanner_.Accept(); // Node* nodeRight = Expr(); // node = new AddNode(node, nodeRight); //} //else if (token == TOKEN_MINUS) //{ // scanner_.Accept(); // Node* nodeRight = Expr(); // node = new SubNode(node, nodeRight); //} if (token == TOKEN_PLUS || token == TOKEN_MINUS) { // Expr := Term { ('+' | '-') Term } MultipleNode* multipleNode = new SumNode(node); do { scanner_.Accept(); Node* nextNode = Term(); multipleNode->AppendChild(nextNode, (token == TOKEN_PLUS)); token = scanner_.Token(); } while (token == TOKEN_PLUS || token == TOKEN_MINUS); node = multipleNode; } return node; } Node* Parser::Term() { Node* node = Factor(); EToken token = scanner_.Token(); //if (token == TOKEN_MULTIPLY) //{ // scanner_.Accept(); // Node* nodeRight = Term(); // node = new MultiplyNode(node, nodeRight); //} //else if (token == TOKEN_DIVIDE) //{ // scanner_.Accept(); // Node* nodeRight = Term(); // node = new DivideNode(node, nodeRight); //} if (token == TOKEN_MULTIPLY || token == TOKEN_DIVIDE) { // Term := Factor { ('*' | '/') Factor } MultipleNode* multipleNode = new ProductNode(node); do { scanner_.Accept(); Node* nextNode = Factor(); multipleNode->AppendChild(nextNode, (token == TOKEN_MULTIPLY)); token = scanner_.Token(); } while (token == TOKEN_MULTIPLY || token == TOKEN_DIVIDE); node = multipleNode; } return node; }