编程实战:类C语法的编译型脚本解释器(五)变量表

系列入口:

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

        本文介绍变量表的实现。

目录

一、变量表的组织结构

二、代码

2.1 变量块

2.2 变量表(栈)

2.3 变量层级

2.4 变量查找


一、变量表的组织结构

        堆栈结构,进入一层新建一个层级,退出一层则丢弃整个层。也就是个栈结构,每层又是个数组。

        查找时自顶向下逐级查找,直到最后的全局变量(包括执行脚本时传入的预设变量)。

        每层是个数组,这会不会有性能问题?作为脚本,里面写几十上百个变量可能性不大,遍历足够了。

二、代码

2.1 变量块

		//变量表struct T_VARIABLE_BLOCK : public vector<pair<string, Variable > >{bool AddVariable(string const& var_name, Variable const& var){for (const_iterator it = begin(); it != end(); ++it){if (it->first == var_name){return false;}}push_back(pair<string, Variable >(var_name, var));return true;}Variable* FindVariable(string const& var_name)const{return FindVariable(var_name.c_str());}Variable* FindVariable(char const* var_name)const{for (const_reverse_iterator it = rbegin(); it != rend(); ++it){if (it->first != var_name){continue;}return (Variable*)&it->second;}return NULL;}};

        继承自vector,只有添加和查找两个功能。

        添加时先检查是否存在,查找时顺序查找。

2.2 变量表(栈)

		class T_VARIABLE_S{private:typedef vector<T_VARIABLE_BLOCK > T_DATA;T_VARIABLE_BLOCK* m_pEnvs;//指向环境变量T_VARIABLE_BLOCK* m_pGlobals;//指向全局变量long m_Globals_count;//全局变量个数T_VARIABLE_BLOCK* m_pParams;//指向参数T_DATA m_local_variables;//局部变量public:T_VARIABLE_S() :m_pEnvs(NULL), m_pGlobals(NULL), m_Globals_count(-1), m_pParams(NULL) {}long getGlobalCount()const { return m_pGlobals->size(); }void T_VARIABLE_S_init(T_VARIABLE_BLOCK* pEnv, T_VARIABLE_BLOCK* pG, long Globals_count, T_VARIABLE_BLOCK* pP){m_pEnvs = pEnv;m_pGlobals = pG;m_Globals_count = Globals_count;m_pParams = pP;m_local_variables.clear();}void T_VARIABLE_S_init(T_VARIABLE_BLOCK const* pEnv, T_VARIABLE_BLOCK const* pG, long Globals_count, T_VARIABLE_BLOCK const* pP){m_pEnvs = (T_VARIABLE_BLOCK*)pEnv;m_pGlobals = (T_VARIABLE_BLOCK*)pG;m_Globals_count = Globals_count;m_pParams = (T_VARIABLE_BLOCK*)pP;m_local_variables.clear();}void FromParentVars(T_VARIABLE_S& vars, long Globals_count, T_VARIABLE_BLOCK const* pP){T_VARIABLE_S_init(vars.m_pEnvs, vars.m_pGlobals, Globals_count, pP);}void FromParentVars(T_VARIABLE_S const& vars, long Globals_count, T_VARIABLE_BLOCK const* pP){T_VARIABLE_S_init(vars.m_pEnvs, vars.m_pGlobals, Globals_count, pP);}void PushLevel(){m_local_variables.resize(m_local_variables.size() + 1);//cout << "PushLevel " << m_datas.size() << endl;}void PopLevel(){if (m_local_variables.size() > 0)m_local_variables.resize(m_local_variables.size() - 1);//cout << "PopLevel " << m_datas.size() << endl;}bool AddVariable(string const& var_name, Variable const& var){if (NULL != FindVariable(var_name))return false;if (0 == m_local_variables.size()){//全局变量m_pGlobals->push_back(pair<string, Variable >(var_name, var));}else{//局部变量m_local_variables.rbegin()->push_back(pair<string, Variable >(var_name, var));}return true;}Variable* FindVariable(string const& var_name)const{return FindVariable(var_name.c_str());}Variable* FindVariable(char const* var_name)const{long count;//从顶层向底层查找for (T_DATA::const_reverse_iterator it = m_local_variables.rbegin(); it != m_local_variables.rend(); ++it){for (T_VARIABLE_BLOCK::const_iterator it_block = it->begin(); it_block != it->end(); ++it_block){if (it_block->first != var_name){continue;}return (Variable*)&it_block->second;}}//再找参数count = m_pParams->size();for (--count; count >= 0; --count){if ((*m_pParams)[count].first != var_name){continue;}return (Variable*) & (*m_pParams)[count].second;}//再找全局变量count = (m_Globals_count < 0 ? m_pGlobals->size() : m_Globals_count);if (m_Globals_count >= 0 && m_Globals_count > (long)m_pGlobals->size()){cout << "错误的有效全局变量个数 " << m_Globals_count << " 最大 " << m_pGlobals->size() << endl;return NULL;}for (--count; count >= 0; --count){if ((*m_pGlobals)[count].first != var_name){continue;}return (Variable*) & (*m_pGlobals)[count].second;}//最后找环境变量for (T_VARIABLE_BLOCK::const_reverse_iterator it = m_pEnvs->rbegin(); it != m_pEnvs->rend(); ++it){if (it->first != var_name){continue;}return (Variable*)&it->second;}return NULL;}string ToString(long level = 0)const{stringstream ret;ret << this << endl;long n = 0;ret << "环境变量:" << endl;for (T_VARIABLE_BLOCK::const_iterator it = m_pEnvs->begin(); it != m_pEnvs->end(); ++it){ret << n << " : " << it->first << " : " << it->second.ToString() << endl;++n;}ret << "全局变量:有效数" << this->m_Globals_count << endl;for (T_VARIABLE_BLOCK::const_iterator it = m_pGlobals->begin(); it != m_pGlobals->end(); ++it){ret << n << " : " << it->first << " : " << it->second.ToString() << endl;++n;}ret << "参数:" << endl;for (T_VARIABLE_BLOCK::const_iterator it = m_pParams->begin(); it != m_pParams->end(); ++it){ret << n << " : " << it->first << " : " << it->second.ToString() << endl;++n;}ret << "局部变量:" << endl;for (T_DATA::const_iterator it = m_local_variables.begin(); it != m_local_variables.end(); ++it){for (T_VARIABLE_BLOCK::const_iterator it_block = it->begin(); it_block != it->end(); ++it_block){//if(it_block->second->isconst)continue;ret << n << " : " << it_block->first << " : " << it_block->second.ToString() << endl;}++n;}return ret.str();}};

        这个类的数据包含四部分:

  • 预设变量(环境变量),是编译和执行时传入的
  • 全局变量,脚本里定义的,配合m_Globals_count即可确定脚本此处可以使用的全局变量(只有此处之前定义的全局变量可以使用)
  • 参数,对于通过插件提供的自定义函数,每个参数都有名字,都是一个可用的变量
  • 局部变量,是个栈,每进入一层嵌套语句块增加一级

        由于全局变量所在位置局部变量栈必然是空的,所以AddVariable直接用局部变量表是否为空来判断是否是全局变量。

        预设变量和全局变量是统一的,所以是个指针。当然全局变量还需要m_Globals_count来指出可用的全局变量个数。(似乎m_Globals_count是多余的,因为如果引用后面定义的全局变量根本编译不下去

2.3 变量层级

        每进入一个新的层级就执行一次PushLevel,新添变量总是添加在最后一级。

        按照新的C标准,for循环是个新的层级,for循环的初始化语句定义的变量仅仅能在for循环里面使用。每个大括号也都表示一个新的层级。

2.4 变量查找

        参数查找顺序为局部变量-参数-全局变量-预设变量,这个顺序是符合类C语言通常的规则的。

        由于变量添加的时候已经做了同样规则的查找,因此确保不会存在同名变量覆盖。

        允许同名变量覆盖不是个好主意,所以我觉得没必要支持。

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

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

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

相关文章

【【Micro Blaze 的 最后补充 与 回顾 】】

Micro Blaze 的 最后补充 与 回顾 Micro Blaze 最小系统 以 MicroBlaze 为核心、LocalMemory&#xff08;片上存储&#xff09;为内存&#xff0c;加上传输信息使用的 UART串口就构成了嵌入式最小系统。当程序比较简单时&#xff0c;Local Memory 可以作为程序的运行空间以及…

VUE语法--img图片不显示/img的src动态赋值图片显示

1、问题概述 常见情景1&#xff1a;在VUE中使用img显示图片的时候&#xff0c;通过传参的方式传入图片的路径和名称&#xff0c;VUE不加载本地资源而是通过http://localhost:8080/...的地址去加载网络资源&#xff0c;从而出现了图片无法显示的情况。 常见情景2&#xff1a;针…

python装饰器解析(关键点:高阶函数、嵌套函数)(参数化装饰器、类装饰器)

文章目录 Python装饰器解析什么是Python装饰器基础理解 如何创建装饰器&#xff08;关键点&#xff1a;高阶函数、嵌套函数&#xff09;创建基础装饰器 使用装饰器使用示例 装饰器的返回值参数化装饰器创建参数化装饰器语法示例使用示例 类装饰器创建类装饰器语法示例使用示例 …

Javaweb之Vue组件库Element案例异步数据加载的详细解析

4.4.3.6 异步数据加载 4.4.3.6.1 异步加载数据 对于案例&#xff0c;我们只差最后的数据了&#xff0c;而数据的mock地址已经提供&#xff1a;http://yapi.smart-xwork.cn/mock/169327/emp/list 我们最后要做的就是异步加载数据&#xff0c;所以我们需要使用axios发送ajax请…

C++内联函数

目录 一&#xff0c;概念 二&#xff0c;特性 三&#xff0c;与内联有关的面试题 四&#xff0c;auto关键字&#xff08;C11&#xff09; auto的使用细则 auto 不能推导的场景 基于范围的for循环&#xff08;C11&#xff09; 范围for的使用条件 五&#xff0c;指针空值…

解决vscode中html部分无法嵌套注释

不管是React项目还是Vue项目&#xff0c;相信你一定遇到过同样的问题&#xff0c;如果想要注释的结构内部也存在注释&#xff0c;那么编译器会报以下问题 使用 HTML-Comment 这个插件即可解决问题 选中需要注释的区域并根据系统输入快捷键&#xff0c;可以发现就算嵌套了注释…

matplotilb画图

Matplotlib 是支持 Python 语言的开源绘图库&#xff0c;因为其支持丰富的绘图类型、简单的绘图方式以及完善的接口文档&#xff0c;深受 Python 工程师、科研学者、数据工程师等各类人士的喜欢。Matplotlib 拥有着十分活跃的社区以及稳定的版本迭代&#xff0c;当我们使用 Pyt…

【Windows】如何实现 Windows 上面的C盘默认文件夹的完美迁移

如何实现 Windows 上面的C盘默认文件夹的完美迁移 1. 遇到的问题 在我想迁移C盘的 下载 和 视频 文件夹的时候&#xff0c;遇到了这样的问题&#xff0c;在迁移之后&#xff0c;我显卡录像的视频还是保存到了C盘默认位置里&#xff0c;以及我迁移了 下载 之后下载的盘依然是在…

轻盈悦耳的运动型气传导耳机,还有条夜跑灯,哈氪聆光体验

我平时出门不管是散步、骑行&#xff0c;还是坐公交的时候&#xff0c;都喜欢戴上耳机听音乐&#xff0c;这可以让我放松心情。现在市面上的耳机还是以真无线为主&#xff0c;选择虽多&#xff0c;但不适合户外使用&#xff0c;听不见外界的声音&#xff0c;运动时还容易脱落&a…

【附代码】Python函数性能测试(perfplot)

文章目录 相关文献测试电脑配置展开元素是list的list在numpy数组上映射函数的最有效方法数组numpy中唯一值的最有效频率计数方法反转numpy数组的最有效方法如何向 numpy 数组添加额外的列将 numpy 矩阵初始化为零或一以外的值 作者&#xff1a;小猪快跑 基础数学&计算数学&…

SpringMVC常用注解和用法总结

目标&#xff1a; 1. 熟悉使用SpringMVC中的常用注解 目录 前言 1. Controller 2. RestController 3. RequestMapping 4. RequestParam 5. PathVariable 6. SessionAttributes 7. CookieValue 前言 SpringMVC是一款用于构建基于Java的Web应用程序的框架&#xff0c;它通…

Debian12配置ssh服务器

Debian12配置ssh服务器 安装ssh-server sudo apt install openssh-server启动ssh sudo systemctl start ssh启用ssh sudo systemctl enable ssh查看ssh状态 sudo systemctl status ssh可以看到有enabled和running字样 说明ssh启用成功 连接到服务器 # username是你的用…

Lag-Llama:基于 LlaMa 的单变量时序预测基础模型

文章构建了一个通用单变量概率时间预测模型 Lag-Llama&#xff0c;在来自Monash Time Series库中的大量时序数据上进行了训练&#xff0c;并表现出良好的零样本预测能力。在介绍Lag-Llama之前&#xff0c;这里简单说明什么是概率时间预测模型。概率预测问题是指基于历史窗口内的…

基于Java SSM框架实现师生交流答疑作业系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现师生交流答疑作业系统演示 摘要 在新发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;人们对师生交流平台越来越重视&#xff0c;更好的实…

CSP-坐标变换(其二)

问题描述 对于平面直角坐标系上的坐标 (x,y)&#xff0c;小 P 定义了如下两种操作&#xff1a; 拉伸 k 倍&#xff1a;横坐标 x 变为 kx&#xff0c;纵坐标 y 变为 ky&#xff1b; 旋转 θ&#xff1a;将坐标 (x,y) 绕坐标原点 (0,0) 逆时针旋转 θ 弧度&#xff08;0≤θ<…

【开源视频联动物联网平台】SIP协议的特点

SIP&#xff08;Session Initiation Protocol&#xff09;协议是一种用于建立、修改和终止多媒体通信会话的通信协议。在互联网电话、视频会议、即时消息传递和多媒体通信等领域&#xff0c;SIP协议得到了广泛的应用。可以说&#xff0c;SIP协议已成为目前通信系统协议的主流&a…

java高校实验室排课学生考勤系统springboot+vue

随着各高校办学规模的迅速扩大,学科专业的不断拓宽,传统的实验教学和实验室管理方法已经不能适应学校管理的要求,特别是化学实验室的管理,化学实验室仪器药品繁杂多样,管理任务繁重,目前主要使用人工记录方法管理,使用不便,效率低下,而且容易疏漏.时间一长将产生大量的文件和数…

使用postman请求x5接口

x5接口简介 1.接口样例 {"header"{"appid":"bpmnew_fanwei","sign":"C033162E86E4CADE80C7EB44D68A5AD2","sign_type":"md5","url":"https://oa.mioffice.cn/api/bpm/xm/app/show/tod…

学习80min快速了解大型语言模型(ChatGPT使用)笔记

学习李宏毅&#xff1a;80min快速了解大型语言模型&#xff08;ChatGPT使用&#xff09;笔记 链接&#xff1a;https://www.youtube.com/watch?vwG8-IUtqu-s 1、创建一个属于自己的GPT 目前&#xff0c;GPT4具备一个功能&#xff0c;Create a GPT。利用这个功能可以创建一个…

Linux:服务器管理工具宝塔(bt)安装教程

一、简介 bt宝塔Linux面板是提升运维效率的服务器管理软件&#xff0c;支持一键LAMP/LNMP/集群/监控/网站/FTP/数据库/JAVA等多项服务的管理功能 二、安装 使用 SSH 连接工具&#xff0c;如堡塔SSH终端连接到您的 Linux 服务器后&#xff0c;挂载磁盘&#xff0c;根据系统执…