zoukankan      html  css  js  c++  java
  • 状态机学习(五)解析四则运算式

    将四则运算拆分成一个个数字和符号后

    就进行运算分析

    使用以下语法规则:(摘录自《自编编程语言》)

    expression:

    term:

    primary expression:

     代码如下:

    #pragma once
    #include <string>
    #include <deque>
    #include <iostream>
    
    enum TokenType {
    	BAD_TOKEN,
    	NUM_TOKEN,
    	ADD_TOKEN,
    	SUB_TOKEN,
    	MUL_TOKEN,
    	DIV_TOKEN,
    	LPAREN_TOKEN,
    	RPAREN_TOKEN,
    	ENDFILE_TOKEN
    };
    
    class Token {
    private:
    	TokenType type_;
    	std::string valueStr_;
    public:
    	Token() : type_(BAD_TOKEN) {}
    	Token(TokenType t,std::string s) : 
    		type_(t),valueStr_(s) {}
    
    	bool operator ==(const Token& t) {
    		if (type_ == t.type_ &&
    			valueStr_ == t.valueStr_) {
    			return true;
    		}
    		return false;
    	}
    	Token(const Token& t) {
    		if (*this != t) {
    			type_ = t.type_;
    			valueStr_ = t.valueStr_;
    		}
    	}
    
    	bool operator != (const Token& t) {
    		return !(*this == t);
    	}
    
    	Token& operator=(const Token& t) {
    		if (*this != t) {
    			type_ = t.type_;
    			valueStr_ = t.valueStr_;
    		}
    		return *this;
    	}
    	/*void SetType(TokenType type) { type_ = type; }
    	void SetValue(double value) { value_ = value; }
    	void SetValStr(std::string valueStr) { valueStr_ = valueStr; }*/
    	TokenType GetType() { return type_; }
    	std::string GetValStr() { return valueStr_; }
    };
    
    
    class Expression2Tokens {
    	
    	std::string contentStr_;
    	Expression2Tokens& operator=(const Expression2Tokens&) {};
    	Expression2Tokens(const Expression2Tokens&);
    	enum Status {
    		INIT_STATUS,
    		NUM_STATUS,
    		OPERATOR_STATUS,
    		LPAREN_STATUS,
    		RPAREN_STATUS,
    		END_STATUS,
    		ERROR_STATUS
    	};
    public:
    	std::deque<Token> tokenDeque_;
    	Expression2Tokens(std::string s):contentStr_(s){}
    	bool Analyzer();
    	void PrintTokens() {
    		for (std::deque<Token>::iterator it = tokenDeque_.begin();
    			it != tokenDeque_.end(); it++) {
    			std::cout << "type: " << (*it).GetType() << ", string: " << (*it).GetValStr() << std::endl;
    		}
    		std::cout << std::endl;
    	}
    
    };
    
    class ParseExpression {
    	Expression2Tokens	express2token_;
    	ParseExpression& operator=(const ParseExpression&) {};
    	ParseExpression(const ParseExpression&);
    	double result_;
    	double ParseTerm();
    	double ParsePrimaryExpression();
    public:
    	ParseExpression(std::string s) :
    		express2token_(s), result_(0.0){}
    	bool StartParse();
    	double GetResult() { return result_; }
    
    };
    

      

    #include "token.h"
    #include <iostream>
    
    bool Expression2Tokens::Analyzer() {
    	bool bRet = false;
    	size_t index = 0, valueBeg = 0, valueEnd = 0;
    	Status status = INIT_STATUS;
    	for (;index < contentStr_.size();index++)
    	{
    		if (isdigit(contentStr_[index])) {
    			if (status != NUM_STATUS) {
    				status = NUM_STATUS;
    				valueBeg = index;
    			}
    			continue;
    		}
    		//对于 非数字进行判断
    		if (NUM_STATUS == status ) {
    			std::string s(contentStr_.substr(valueBeg, index - valueBeg));
    			Token t(NUM_TOKEN,s);
    			tokenDeque_.push_back(t);
    			valueBeg = 0;
    		}
    
    		if (contentStr_[index] == '+') {
    			Token t(ADD_TOKEN, "+");
    			tokenDeque_.push_back(t);
    			status = OPERATOR_STATUS;
    			continue;
    		}else if (contentStr_[index] == '-') {
    			Token t(SUB_TOKEN, "-");
    			tokenDeque_.push_back(t);
    			status = OPERATOR_STATUS;
    			continue;
    		}else if (contentStr_[index] == '*') {
    			Token t(MUL_TOKEN, "*");
    			tokenDeque_.push_back(t);
    			status = OPERATOR_STATUS;
    			continue;
    		}else if (contentStr_[index] == '/') {
    			Token t(DIV_TOKEN,"/");
    			tokenDeque_.push_back(t);
    			status = OPERATOR_STATUS;
    			continue;
    		}else if (contentStr_[index] == ';')
    		{
    			Token t(ENDFILE_TOKEN, ";");
    			tokenDeque_.push_back(t);
    			status = END_STATUS;
    			bRet = true;
    			return bRet;
    		}
    		
    		else {
    			std::cerr << "analyzer error (" << contentStr_[index] << ")" <<  std::endl;
    			status = ERROR_STATUS;
    			return false;
    		}
    	}
    
    	return bRet;
    }
    
    double ParseExpression::ParsePrimaryExpression() {
    	Token token;
    	token = express2token_.tokenDeque_.front();
    	if (token.GetType() == NUM_TOKEN) {
    		//return  atof(token.GetValStr().c_str());
    		express2token_.tokenDeque_.pop_front();
    		return stod(token.GetValStr());
    	}
    	std::cerr << "syntax error." << std::endl;
    	exit(1);
    	return 0.0;
    }
    
    
    
    
    double ParseExpression::ParseTerm() {
    	double dRet;
    	double v;
    
    	Token token;
    
    	dRet = ParsePrimaryExpression();
    	for (;;) {
    		token = express2token_.tokenDeque_.front();
    		if (token.GetType() != MUL_TOKEN
    			&& token.GetType() != DIV_TOKEN) {
    			break;
    		}
    		express2token_.tokenDeque_.pop_front();
    		v = ParsePrimaryExpression();
    		if (token.GetType() == MUL_TOKEN) {
    			dRet *= v;
    		}
    		else if (token.GetType() == DIV_TOKEN) {
    			dRet /= v;
    		}
    	}
    
    	return dRet;
    }
    
    
    bool ParseExpression::StartParse() {
    	bool bRet = false;
    	if (!express2token_.Analyzer())
    		return bRet;
    	express2token_.PrintTokens();
    	
    
    	double v;
    	Token token;
    
    	result_ = ParseTerm();
    	for (;;) {
    		token = express2token_.tokenDeque_.front();
    		if (token.GetType() != ADD_TOKEN &&
    			token.GetType() != SUB_TOKEN) {
    			break;
    		}
    		express2token_.tokenDeque_.pop_front();
    		v = ParseTerm();
    		if (token.GetType() == ADD_TOKEN) {
    			result_ += v;
    		}
    		else if (token.GetType() == SUB_TOKEN) {
    			result_ -= v;
    		}
    	}
    
    	bRet = true;
    	return bRet;
    
    }
    

      测试代码如下:

    // MyParse.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "token.h"
    #include <iostream>
    
    int main()
    {
    	
    	Expression2Tokens e("1+2/3*45-67-89+999;");
    	if (e.Analyzer()) {
    		e.PrintTokens();
    	}
    
    	ParseExpression p("132+243/7*4455-6-89+34;");
    	if(p.StartParse())
    		std::cout << "result: " << p.GetResult() << std::endl;
        return 0;
    }
    

      

    type: 1, string: 1
    type: 2, string: +
    type: 1, string: 2
    type: 5, string: /
    type: 1, string: 3
    type: 4, string: *
    type: 1, string: 45
    type: 3, string: -
    type: 1, string: 67
    type: 3, string: -
    type: 1, string: 89
    type: 2, string: +
    type: 1, string: 999
    type: 8, string: ;

    type: 1, string: 132
    type: 2, string: +
    type: 1, string: 243
    type: 5, string: /
    type: 1, string: 7
    type: 4, string: *
    type: 1, string: 4455
    type: 3, string: -
    type: 1, string: 6
    type: 3, string: -
    type: 1, string: 89
    type: 2, string: +
    type: 1, string: 34
    type: 8, string: ;

    result: 154723
    请按任意键继续. . .

  • 相关阅读:
    20080619 SQL SERVER 输入 NULL 的快捷键
    20090406 Adobe的“此产品的许可已停止工作”错误的解决办法
    20080908 Office Powerpoint 2007 不能输入中文的解决办法
    20080831 ClearGertrude Blog Skin 's cnblogs_code class
    20080603 Facebook 平台正式开放
    20080519 安装 Microsoft SQL Server 2000 时提示 创建挂起的文件操作
    test
    Linux—fork函数学习笔记
    SOA的设计理念
    Why BCP connects to SQL Server instance which start with account of Network Service fail?
  • 原文地址:https://www.cnblogs.com/itdef/p/6172317.html
Copyright © 2011-2022 走看看