将四则运算拆分成一个个数字和符号后
就进行运算分析
使用以下语法规则:(参考《自编编程语言》)
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
请按任意键继续. . .