讲师中心 微信公众号
AI工具推荐 视频效率加速

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

阿静姑娘_5815

阿静姑娘_5815

发布时间:2026-04-13 22:41:05

|

227人浏览过

|

来源于php中文网

原创

直接写 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 必须拆成不同层级函数,否则结合性和优先级全乱。

实操建议:

立即学习“C++免费学习笔记(深入)”;

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

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

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

实操建议:

立即学习“C++免费学习笔记(深入)”;

  • 用索引指针 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 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

实操建议:

立即学习“C++免费学习笔记(深入)”;

  • 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。

实操建议:

立即学习“C++免费学习笔记(深入)”;

  • 初期用 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 维护位置信息(行/列),导致报错时只能给偏移量。真要调试复杂表达式,这个信息比语法树还先得有。

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
string转int
string转int

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

6399

2023.08.02

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

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

6084

2023.10.24

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

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

2964

2024.02.23

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

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

1772

2025.10.17

while的用法
while的用法

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

354

2023.09.25

登录token无效
登录token无效

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

13826

2023.09.14

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

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

1645

2023.09.14

token怎么获取
token怎么获取

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

3797

2023.12.21

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

0

2026.10.21

热门下载

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

精品课程

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

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

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

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn