面向对象版计算器(八)

让表达式计算器支持变量赋值

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;
}






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值