状态机学习 解析四则运算式 语法分析

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

就进行运算分析

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

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

测试代码如下:

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


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值