状态机学习 解析四则运算式 语法分析
来源:互联网 发布:蜂窝移动数据设置 编辑:程序博客网 时间:2024/06/06 19:00
将四则运算拆分成一个个数字和符号后
就进行运算分析
使用以下语法规则:(参考《自编编程语言》)
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 0
- 状态机学习 解析四则运算式 语法分析
- 状态机学习 解析INI文件
- 基于状态机的四则运算计算器
- 状态机解析
- 使用 正则表达式 解析四则运算式
- 状态机学习
- 语法分析之antlr学习
- 语法分析 -- 学习笔记
- Redy语法分析--一个简单的四则运算计算器
- 四则运算表达式解析
- 解析表达式 四则运算
- Qt解析四则运算表达式
- 状态机之C++解析
- 状态机之C++解析
- 状态机之C++解析
- 状态机之C++解析
- DFA状态机解析字符串
- 状态机之C++解析
- PPP协议简介
- eee
- MFC获取Windows DPI
- opensips 安装 rtpproxy 教程
- linux每天一小步---touch命令详解
- 状态机学习 解析四则运算式 语法分析
- android真机调试的问题
- MYSQL Group Replication搭建过程
- Java面试题列表2
- 策略模式Strategy
- Globus Toolkit Installation on CentOS
- js给当前跳转的页面a标签添加class或者id
- srpingmvc4开发学习(第一讲)
- 登录token值的demo