让表达式计算器支持变量赋值
a=5
Node.h:
添加几个方法 主要用来确定赋值运算符
class Node : private Noncopyable
{
public:
virtual double Calc() const = 0;
virtual bool IsLvalue() const
{
return false;
}
virtual void Assign(double)
{
assert(!"Assign called incorrectlly.");
}
virtual ~Node() {}
};
存储变量
class VariableNode : public Node
{
public:
VariableNode(unsigned int id, Storage& storage)
: id_(id), storage_(storage) {}
double Calc() const;
bool IsLvalue() const;
void Assign(double val);
private:
const unsigned int id_;
Storage& storage_;
};
double VariableNode::Calc() const
{
double x = 0.0;
if (storage_.IsInit(id_))
{
x = storage_.GetValue(id_);
}
else
{
std::cout<<"Use of uninitialized variable."<<std::endl;
}
return x;
}
bool VariableNode::IsLvalue() const
{
return true;
}
void VariableNode::Assign(double val)
{
storage_.SetValue(id_, val);
}
//赋值运算符
class AssignNode : public BinaryNode
{
public:
AssignNode(Node* left, Node* right)
: BinaryNode(left, right)
{
assert(left->IsLvalue());
}
double Calc() const;
};
double AssignNode::Calc() const
{
double x = 0.0;
x = right_->Calc();
left_->Assign(x);
return x;
}
Scanner扫描器的改变
#ifndef _SCANNER_H_
#define _SCANNER_H_
#include <string>
enum EToken
{
TOKEN_END,
TOKEN_ERROR,
TOKEN_NUMBER,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_MULTIPLY,
TOKEN_DIVIDE,
TOKEN_LPARENTHESIS,
TOKEN_RPARENTHESIS,
TOKEN_IDENTIFIER,//标识变量
TOKEN_ASSIGN//标识赋值运算符
};
class Scanner
{
public:
explicit Scanner(const std::string& buf);
void Accept();
double Number() const;
std::string GetSymbol() const;
EToken Token() const;
private:
void SkipWhite();
const std::string buf_;
unsigned int curPos_;
EToken token_;
double number_;
std::string symbol_; //存储变量
};
#endif // _SCANNER_H_
void Scanner::Accept()
{
SkipWhite();
switch (buf_[curPos_])
{
case '+':
token_ = TOKEN_PLUS;
++curPos_;
break;
case '-':
token_ = TOKEN_MINUS;
++curPos_;
break;
case '*':
token_ = TOKEN_MULTIPLY;
++curPos_;
break;
case '/':
token_ = TOKEN_DIVIDE;
++curPos_;
break;
case '=':
token_ = TOKEN_ASSIGN;
++curPos_;
break;
case '(':
token_ = TOKEN_LPARENTHESIS;
++curPos_;
break;
case ')':
token_ = TOKEN_RPARENTHESIS;
++curPos_;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
token_ = TOKEN_NUMBER;
char* p;
number_ = strtod(&buf_[curPos_], &p);
curPos_ = p - &buf_[0];
break;
case '\0': case '\n': case '\r': case EOF:
token_ = TOKEN_END;
break;
default:
if (isalpha(buf_[curPos_]) || buf_[curPos_] == '_')
{
token_ = TOKEN_IDENTIFIER;
symbol_.erase();
char ch = buf_[curPos_];
do
{
symbol_ += ch;
++curPos_;
ch = buf_[curPos_];
} while (isalnum(ch) || ch == '_');
}
else
token_ = TOKEN_ERROR;
break;
}
}
Calc类的编写(可以集成在parser中)
#ifndef _CALC_H_
#define _CALC_H_
#include "SymbolTable.h"
#include "Storage.h"
#include <string>
class Parser;
class Calc
{
friend class Parser;
public:
Calc() : storage_(symTbl_) {}
private:
Storage& GetStorage()
{
return storage_;
}
unsigned int AddSymbol(const std::string& str);
unsigned int FindSymbol(const std::string& str) const;
SymbolTable symTbl_;
Storage storage_;
};
#endif // _CALC_H_
#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);
}
parser解析器
#ifndef _PARSER_H_
#define _PARSER_H_
class Scanner;
class Node;
class Calc;
enum STATUS
{
STATUS_OK,
STATUS_ERROR,
STATUS_QUIT
};
class Parser
{
public:
Parser(Scanner& scanner, Calc& calc);
void Parse();
Node* Expr();
Node* Term();
Node* Factor();
double Calculate() const;
private:
Scanner& scanner_;
Calc& calc_;//添加一个变量calc
Node* tree_;
STATUS status_;
};
#endif // _PARSER_H_
Node* Parser::Expr()
{
Node* node = Term();
EToken token = scanner_.Token();
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;
}
else if (token == TOKEN_ASSIGN)
{
// Expr := Term = Expr
scanner_.Accept();
Node* nodeRight = Expr();
if (node->IsLvalue())
{
node = new AssignNode(node, nodeRight);
}
else
{
status_ = STATUS_ERROR;
std::cout<<"The left-hand side of an assignment must be a variable"<<std::endl;
// Todo 抛出异常
}
}
return node;
}
Node* Parser::Factor()
{
Node* node = 0;
EToken token = scanner_.Token();
if (token == TOKEN_LPARENTHESIS)
{
scanner_.Accept(); // accept '('
node = Expr();
if (scanner_.Token() == TOKEN_RPARENTHESIS)
{
scanner_.Accept(); // accept ')'
}
else
{
status_ = STATUS_ERROR;
// Todo:抛出异常
std::cout<<"missing parenthesis"<<std::endl;
node = 0;
}
}
else if (token == TOKEN_NUMBER)
{
node = new NumberNode(scanner_.Number());
scanner_.Accept();
}
else if (token == TOKEN_IDENTIFIER)
{
std::string symbol = scanner_.GetSymbol();
unsigned int id = calc_.FindSymbol(symbol);
scanner_.Accept();
if (id == SymbolTable::IDNOTFOUND)
{
id = calc_.AddSymbol(symbol);
}
node = new VariableNode(id, calc_.GetStorage());
}
else if (token == TOKEN_MINUS)
{
scanner_.Accept(); // accept minus
node = new UMinusNode(Factor());
}
else
{
status_ = STATUS_ERROR;
// Todo:抛出异常
std::cout<<"not a valid expression"<<std::endl;
node = 0;
}
return node;
}