C++实现简单递归下降解析器 _ 解析数学表达式逻辑【源码】

阿静姑娘_5815

阿静姑娘_5815

2026-04-13

227人浏览

原创

直接写 parse_expression() 易崩因未分层处理优先级,须按+−、*/、因子分三级函数,用循环消除左递归,配合token流定位与位置信息。

c++实现简单递归下降解析器 _ 解析数学表达式逻辑【源码】

为什么直接写 parse_expression() 容易崩在加减优先级上

递归下降解析器不是把文法照抄成函数就完事——数学表达式里 + 和 * 优先级不同,如果让 parse_expression() 一把抓所有运算符,很快会把 1 + 2 * 3 解成 (1 + 2) * 3 == 9,而不是正确的 1 + (2 * 3) == 7。本质是文法没分层:expression → term (+|−) expression 和 term → factor (*|/) term 必须拆成不同层级函数,否则结合性和优先级全乱。

实操建议:

  • 按优先级从低到高设计函数链:最外层 parse_expression() 只处理 +/−,内部调用 parse_term();parse_term() 只处理 *//,内部调用 parse_factor()
  • 每个函数都采用「左递归消除」写法:用 while 循环吃掉连续同级运算符,不真写递归调用自己(C++ 栈深度有限,且左递归会无限展开)
  • 提前校验 token 类型,比如 parse_factor() 开头必须是数字、( 或一元 -,否则报错并返回默认值或抛异常

std::string 做输入时怎么安全取下一个 token

很多人直接用 std::string::substr() 切片拼新字符串,结果每次解析一个 token 就拷贝一次子串,表达式长一点性能断崖下跌。更糟的是,若 token 边界判断出错(比如把 12.34 当成两个整数),后续全错。

实操建议:

  • 用索引指针 size_t pos 在原 std::string 上滑动,只在需要时用 std::string_view(C++17)或 string.substr(pos, len) 提取 token 值,避免中间拷贝
  • 数字 token 解析必须支持整数和浮点:先读整数部分,遇到 . 就继续读小数部分,再检查是否带指数(e/E);别用 std::stod() 直接转——它不报告解析截止位置,无法更新 pos
  • 跳过空白用 std::isspace(static_cast<unsigned char>(s[pos]))</unsigned>,避免 locale 问题;遇到非法字符(如 @、$)立刻报错,不要静默跳过

遇到 Unexpected token ')' 时怎么快速定位括号匹配问题

错误信息本身没用——它只告诉你“现在看到 ),但不该在这儿”。真正问题是:前面的 ( 没被正确消费,或者 parse_factor() 进入 ( 分支后,没严格要求结尾必须是 )。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

实操建议:

  • parse_factor() 中识别到 ( 后,必须调用 parse_expression(),然后**立刻**检查下一个 token 是否为 );如果不是,说明括号内表达式结束得太早或根本没闭合
  • 维护一个轻量级 token 流包装器,带 peek()(看下一个不消耗)和 consume()(确认消耗),这样在报错时能打印「expected ), got + at position 15」,比笼统的 “unexpected” 有用得多
  • 测试用例一定要覆盖嵌套:如 ((1 + 2) * 3)、1 + (2 * (3 + 4)),单层括号掩盖不了匹配逻辑漏洞

C++11 能用但别硬扛的坑:异常、移动语义与 AST 构建

想返回解析树?别在每层函数里 new 一堆 ASTNode*——裸指针管理极易泄漏,而 C++11 不支持 std::make_unique 的完美转发(直到 C++14)。更现实的路径是:先做计算器式解析器(直接计算值),验证逻辑正确后再升级为构建 AST。

实操建议:

  • 初期用 double parse_expression() 返回数值,函数内局部变量存中间结果;等全部运算符、括号、一元负号都跑通了,再考虑引入 struct Expr { enum Type; std::unique_ptr<expr> left, right; double value; };</expr>
  • 一元负号(-5)必须和二元减号(3 - 5)区分:在 parse_factor() 开头检查是否为 -,若是则递归调用自身并取负,**不能**塞进 parse_term() 里处理
  • 除零不抛异常,返回 std::numeric_limits<double>::quiet_NaN()</double>,由上层决定是否检查;C++11 的 std::isnan() 可用,比 try/catch 轻量

最常被跳过的细节是:没有为每个 token 维护位置信息(行/列),导致报错时只能给偏移量。真要调试复杂表达式,这个信息比语法树还先得有。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6459

3

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6104

49

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

2984

5

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

1792

13

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.25

354

5

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

2023.09.14

13886

6

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.14

1645

5

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

2023.12.21

3817

3

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

2024.03.01

5981

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习