0

0

C++如何实现简单的脚本解释器?(词法+语法分析)

尼克

尼克

发布时间:2026-02-19 14:58:06

|

877人浏览过

|

来源于php中文网

原创

词法分析器应采用状态机区分in_code/in_string/in_comment状态,仅在in_code跳过空白,遇/后预读判断注释或运算符;递归下降需消除左递归,改用迭代处理同级运算符并显式编码优先级;作用域用vector栈管理,变量查找从栈顶向下扫描且声明只写入栈顶;ast须分层体现优先级,如+节点右子树必须为term节点。

c++如何实现简单的脚本解释器?(词法+语法分析)

词法分析器怎么写才不卡在空格和注释上

直接手撸 Tokenizer 时,最常崩在没统一处理空白符和行内注释。比如 // 后面跟换行、/* ... */ 跨行、还有字符串里嵌套的 //,全当成注释就错了。

实操建议:

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

  • 用状态机驱动,区分 IN_CODE / IN_STRING / IN_COMMENT 三种主状态,字符串里的 "//" 不触发注释逻辑
  • 跳过空白只在 IN_CODE 状态做;遇到 / 先 peek 下一个字符:是 / 就吞掉整行,是 * 就进多行注释状态,否则当除法运算符
  • 别用 std::stringstream 按空格切——它吃掉换行又不报错,导致后续行号错乱;改用 std::string::find_first_not_of(" \t\n\r") 定位 token 起点

递归下降解析器怎么避免左递归崩溃

parseExpression() 时照着“表达式 → 项 + 表达式”硬套文法,立刻栈溢出。C++ 没尾调用优化,无限递归不是报错,是直接段错误。

实操建议:

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

  • 把左递归改造成迭代:用 while 循环处理同级运算符(如 +-),每次循环只 consume 一个操作符+下一个项
  • 优先级必须显式编码:先调 parseTerm()(处理 *//),再在 parseExpression() 里检查是否为 +-,而不是让 parseExpression() 自己调自己
  • 每个解析函数返回 std::unique_ptr<node></node>,别传引用或裸指针——临时对象生命周期一乱,AST 节点就 dangling

变量作用域怎么管才不会覆盖全局变量

int x = 1; { int x = 2; print(x); } 输出 2 没问题,但退出块后继续用 x 却拿到 1,说明作用域链没连对。常见错误是所有变量都往全局 std::map<:string value></:string> 里塞,压根没嵌套。

Ink For All
Ink For All

AI写作和营销助手,精心设计的 UI

下载

实操建议:

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

  • std::vector<:unordered_map value>></:unordered_map> 当作用域栈,push_back({}) 进新块,pop_back() 出块
  • 查找变量时从栈顶往下 scan,但声明变量只写入栈顶 map;别在查找失败时自动 fallback 到全局——那是 JS 的坑,C++ 解释器该严格报 undefined identifier 'x'
  • 函数参数也得进当前作用域,且必须在函数体执行前绑定,否则闭包捕获时值是未初始化的垃圾

为什么 eval("1 + 2 * 3") 返回 9 而不是 7

这说明运算符优先级没生效,所有二元操作都当成了左结合、同级处理。根本原因在于 AST 构建阶段没按优先级分层,而是把 +* 都塞进同一个节点类型里。

实操建议:

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

  • AST 节点类型要分层:BinaryOpNode 存操作符,但父节点结构体现结合性——比如 + 节点的右子树必须是 Term 节点(含 *//),不能是另一个 +
  • 求值时别用 switch 堆积所有运算符逻辑;按节点类型 dispatch:evalAddNode() 专门处理加法,内部确保左右子树已求值完毕
  • 测试用例必须覆盖混合优先级:eval("a = 1 + 2 * 3; a - 4 / 2"),结果应是 5,不是 36

真正麻烦的是错误恢复——词法错一个字符,后面几十行全报错。先保证单行语法正确能跑通,再考虑报错位置精准和继续解析。其他都是后续迭代的事。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

192

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

12

2026.02.03

string转int
string转int

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

770

2023.08.02

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

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

1553

2023.10.24

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

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

237

2024.02.23

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

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

127

2025.10.17

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

559

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

435

2024.03.13

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

660

2026.02.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.7万人学习

C 教程
C 教程

共75课时 | 4.8万人学习

C++教程
C++教程

共115课时 | 18.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号