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
    请按任意键继续. . .

  • 相关阅读:
    数据库分表分库
    rabbitMq 集群
    马哥博客作业第七周
    马哥博客作业第六周
    马哥博客作业第一阶段考试
    马哥博客作业第四周
    马哥博客作业第三周
    马哥博客作业第二周
    马哥博客作业第一周
    03-MySQL数据库表的基本操作
  • 原文地址:https://www.cnblogs.com/itdef/p/6172317.html
Copyright © 2011-2022 走看看