编程实战:类C语法的编译型脚本解释器(八)编译概览

 系列入口:编程实战:类C语法的编译型脚本解释器(系列)-CSDN博客

         前面已经介绍了Token、变量、变量表、表达式和语句,现在进入深水区,介绍编译过程,相当于解释型脚本的解释过程。

        编译的好处是提前发现语法错误,然后可以重复执行几千万次,解释型对此无能为力。

目录

一、代码概览

二、成员变量

三、编译的主逻辑


一、代码概览

        前面介绍的那些代码都是类,可以分开也可以放在一起,我的代表整个脚本的类是这样的:

         这两张截图就是脚本类CScript的全貌,前面介绍的变量表、Token集合、表达式和语句都是这个类的子类(这是无关紧要的,整个代码放在一个名字空间中,也不会在里面掺入别的模块,所以子类还是独立类没有关系)。

        public部分很简单,只有编译和执行的入口。private部分则是一系列互相递归的函数。

二、成员变量

        代码:

	public:string m_source;Variable::types return_type;string script_name;//如果是子函数,这是函数名long count_global_variable;//如果是子函数,这是全局变量个数(只能使用之前定义的全局变量)private:bool m_compiled;bool m_isFunction;//是否是子函数long m_execcount;//执行次数string m_msg;T_VARIABLE_BLOCK m_EnvVariables;//环境变量表,对于子函数,是参数vector<Sentence > m_sentences;//语句组vector<CScript > m_functions;//子函数vector<Expression*> m_NewExpressions;//所有new出来的表达式,析构时要清理

         多解释一下:

类型名称用途
stringm_source脚本源码
Variable::typesreturn_type脚本或子函数的返回值
stringscript_name如果是子函数,这是函数名,否则无意义
longcount_global_variable如果是子函数,这是可用的全局变量的个数,不过由于编译时按顺序编译,运行时又没有动态删除变量的机制,所以其实并不需要这个
boolm_compiled脚本是否编译成功
boolm_isFunction表明本对象是否是子函数
longm_execcount运行计数,此值可以用做业务分析,常年不用的插件可以删掉
stringm_msg如果编译或运行出错,这里是出错信息
T_VARIABLE_BLOCKm_EnvVariables对于脚本,是外部变量(环境变量),对于子函数,是调用参数
vector<Sentence >m_sentences脚本或子函数的所有语句,概念上,脚本或函数就是一组语句
vector<CScript >m_functions脚本的所有子函数
vector<Expression*>m_NewExpressions内部机制,用于清理

        从这个表我们对整个语言的语法结构就比较清晰了:

  • 脚本就是入口参数+语句+返回值
  • 语句就是控制结构和表达式
  • 表达式就是加减乘除和函数调用,以及常量和变量
  • 函数调用就是函数名、参数和返回值
  • 参数就是表达式——又回到表达式
  • 函数就是脚本——又回到最初

        几条简单规则的无限递归——直到常量和变量。

三、编译的主逻辑

        编译入口:

		bool Compile(char const* _source, vector<pair<string, Variable > >* pEnvs = NULL){Init(_source);string str;CTokens tokens;T_VARIABLE_BLOCK currentGlobals;T_VARIABLE_BLOCK currentParams;T_VARIABLE_S curentVars;curentVars.T_VARIABLE_S_init(&m_EnvVariables, &currentGlobals, -1, &currentParams);//当前环境变量和全局变量在子函数中同样有效,必须独立存储try{if (!AddEnvVariableDelcare(pEnvs)){m_msg += "添加环境变量失败\r\n";return false;}if (!tokens.ToTokens(m_source)){m_msg += "编译失败\r\n";return false;}size_t pos = 0;if (!Build(tokens, curentVars, pos)){m_msg += "编译失败\r\n";return false;}}catch (string const& e){m_msg += e;Report(&tokens, curentVars, str);m_msg += str;return false;}catch (char const* s){m_msg += s;Report(&tokens, curentVars, str);m_msg += str;return false;}return true;}

        主要分为三步:

  1. 设置外部变量(环境变量)
  2. 解析Token
  3. 执行编译Build()

        从源码到Token这一步是独立完成的,后续所有操作都基于Token。

        Build()的代码:

		bool Build(CTokens& tokens, T_VARIABLE_S& vars, size_t& pos){bool isFunction = (0 != pos);while (pos < tokens.m_tokens.size()){if (isFunction){if (tokens.IsDelimiter(pos, "}")){break;}}m_sentences.resize(m_sentences.size() + 1);Token* pToken;if (!GetSentence(tokens, vars, m_sentences[m_sentences.size() - 1], pToken, pos))return false;if (!m_sentences[m_sentences.size() - 1].CheckSentence(m_source, vars, false))return false;}m_compiled = true;return true;}

        逻辑非常简单:

  • 如果是子函数而下一个Token是“}”,子函数结束
  • 获取一个语句并检查

        就这么简单。再往后才是真正的深水区。

(这里是结束,但不是整个系列的结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/201253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GO学习之 单例模式 sync.Once

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

js占位符 ${} 使用

JavaScript 占位符 在 JavaScript 编程中&#xff0c;占位符是一种特殊的标记或符号&#xff0c;用于指示代码执行时应替换为实际值。占位符通常用于字符串拼接、格式化输出和动态生成代码等场景。本文将介绍 JavaScript 中常用的占位符&#xff0c;并提供相应的代码示例。 字…

在github中通过action自动化部署 hugo academic theme,实现上传md文件更新博客内容

在github中通过action自动化部署 hugo academic theme 一、GitHub Action自动化部署Hugo博客方法 主要参考&#xff1a;【Hugo网站搭建】GitHub Action自动化部署Hugo博客 次要参考&#xff1a;使用 Github Action 自动部署 Hugo 博客 二、部署过程中遇到的问题和解决办法 …

HarmonyOS鸿蒙操作系统架构

目录 1. 分布式架构&#xff1a; 2. 统一的开发平台&#xff1a; 3. 多内核共享&#xff1a; 4. 自适应界面&#xff1a; 5. AR、VR、MR支持&#xff1a; 6. 安全和隐私保护&#xff1a; 7. AI集成&#xff1a; 8. 应用生态系统&#xff1a; 9. 开源和开放&#xff1a…

C#用MathNet生成矩阵,并打印矩阵元素

文章目录 安装创建和显示矩阵 安装 MathNet.Numerics中提供了线性代数、微积分、特殊函数、概率论、随机函数、插值、最优化等一系列功能&#xff0c;是.net技术中首选的数值计算包。 其中&#xff0c;线性代数包LinearAlgebra包提供了向量、矩阵等数据结构&#xff0c;这些是…

振弦采集仪在土体与岩体监测中的可靠性与精度分析

振弦采集仪在土体与岩体监测中的可靠性与精度分析 振弦采集仪是一种用于土体和岩体监测的重要设备&#xff0c;它可以通过测量振动信号来获取土体或岩体的力学参数&#xff0c;如应力、应变、弹性模量等。而振弦采集仪的可靠性和精度是影响其应用效果的关键因素。 首先&#x…

鸿蒙4.0开发笔记之ArkTS语法基础之条件渲染和循环渲染的使用(十五)

文章目录 一、条件渲染&#xff08;if&#xff09;二、循环渲染&#xff08;ForEach&#xff09; 一、条件渲染&#xff08;if&#xff09; 1、定义 正如其他语言中的if…else…语句&#xff0c;ArkTS提供了渲染控制的能力&#xff0c;条件渲染可根据应用的不同状态&#xff0…

竞赛活动过程中评委亮灯是如何实现的

选秀节目中用到的那种评委爆灯效果要通过软件和硬件一起实现&#xff0c;软件实现在新一轮开始时&#xff0c;统一灭灯&#xff0c;评委通过按钮触发软件打开相应的灯&#xff0c;并自动发出声音。其实用到的物料包括&#xff1a;软件、按钮、灯、工业控制器。软件是核心&#…

virtualbox虚拟机安装ubuntu系统,启动黑屏

我在virtualbox虚拟机里面安装ubuntu系统&#xff0c;某次打开就卡在启动界面了。下面这样&#xff1a;&#xff08;这个截图信息是我在解决了问题之后重新进入ubnutu系统时截取的&#xff0c;不完整&#xff0c;但就是类似这样&#xff09; 报错信息&#xff1a; error: no s…

解决Kettle无法传输生偏字的问题

最近在搞数据传输&#xff0c;然后涉及到人名的时候&#xff0c;难免会碰到生僻字&#xff0c;utf8是无法存储的&#xff0c;然后我把目标表改为utf8mb4&#xff0c;但是还是无法传输生僻字&#xff0c;这就很奇怪了&#xff0c;明明两边的数据库都是MySQL 5.7x&#xff0c;但是…

【QT】容器类

目录 1.容器类概述 2.顺序容器类 2.1 QList 2.2 QLinkedList 2.3 QVector 2.4 QStack 2.5 QQueue 3.关联容器类 3.1 QSet 3.2 QMap 3.3 QMultiMap 3.4 QHash 3.5 QMuItiHash 1.容器类概述 Qt提供了多个基于模板的容器类&#xff0c;这些容器类可以用于存储指定类…

【labview报错,缺少GOOP Development Suite】

操作 当labview报此错误时&#xff0c;第一类情况为缺少包&#xff0c;第二类为所使用的GPU包已失效 以下为第一类缺包的解决方式 登录VIPM&#xff0c;如何安装VIPM查看此贴&#xff1a;VIPM安装 打开VIPM后&#xff0c;右上角输入goop,双击搜索出的安装包 勾选需要安装的包…

Linux部署Kettle(pentaho-server-ce-9.4.0.0-343)记录/配置MySQL存储

下载地址 Kettle 是一个开源的数据集成工具&#xff0c;它是 Pentaho Data Integration&#xff08;PDI&#xff09;项目的一部分。要访问 Kettle 的官方网站&#xff0c;可以通过访问其母公司 Hitachi Vantara 的网站来找到相关信息 官方网站&#xff1a;https://www.hitachi…

uni-app实现返回刷新上一页

方案一 通过监听器实现 page1 uni.$on("refresh", function(data) {if(data.page "page2") {this.reload()} })page2 methods: {handleBack() {uni.$emit("refresh", {page: "page2"})uni.navigateBack()} }方案二 通过页面实例实…

微信小程序:chooseimage从本地相册选择图片或使用相机拍照

文档 https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html 代码示例 const res await uni.chooseImage({count: 1, //默认9sizeType: [original, compressed], //可以…

浪潮信息KeyarchOS EDR 安全防护测评

背景 近几年服务器安全防护越来越受到企业的重视&#xff0c;企业在选购时不再仅仅看重成本&#xff0c;还更看重安全性&#xff0c;因为一旦数据泄露&#xff0c;被暴力破解&#xff0c;将对公司业务造成毁灭性打击。鉴于人们对服务器安全性的看重&#xff0c;本篇文章就来测…

【ArcGIS Pro】探索性插值无法覆盖所需shp范围

做个小记录自用&#xff0c;实际不准。 1 看看就行 pro插值 看看过程就行。有详细过程&#xff0c;类似tutorial https://learn.arcgis.com/zh-cn/projects/interpolate-temperatures-using-the-geostatistical-wizard/ 2 注意用投影坐标系 wgs84转投影坐标系 https://blog…

OSG编程指南<十八>:OSG读写保存文件及对中文字符的支持

基本几何体的绘制只适用于简单的编程&#xff0c;当场景中需要加载一个很复杂的模型时&#xff0c;还是需要从外部导入。osgDB 库 提供了读取二维图像和三维模型的接口&#xff0c;同时&#xff0c;也管理着第三方插件系统&#xff0c;以实现对不同格式文件的读取。 1、OSG 支…

在耳机心率血氧健康检测中应用的穿戴心率血氧接收芯片

时代快速发展的今天&#xff0c;随着生活节奏的加快&#xff0c;工作压力的加大&#xff0c;越来越多的消费者开始关注到自身身体健康&#xff0c;加班熬夜生活不规律&#xff0c;很容易让我们的身体处于亚健康的状态&#xff0c;而心率和体温的变化&#xff0c;就能反应我们身…

报表多源关联

报表多源关联 需求背景 在项目中会遇到多种数据展现在一起的报表。例如部分指标在关系型数据库中&#xff0c;部分指标通过restful接口获得到json&#xff0c;然后根据共同的维度关联一起&#xff0c;形成新的数据集。 解决方案 在硕迪报表中有两种方式实现该多源报表&…