一. 主要流程分析

1:整体处理被 ExpressRunner 托管,可以在这个类里开启一些运行时辅助功能,比如 是否使用Cache中的指令集是否输出详细的执行指令信息 等等,。

首先调用这个方法 ExpressRunner#execute(Sting,IExpressContext):Object ,第一个参数是表达式,第二个是上下文。

2:然后调用 ExpressRunner#parseInstructionSet(String): InstructionSet,把表达式转为指令集。这个方法主要调用两个方法

ExpressParse#parse(String):ExpressNode
ExpressNode 属性有值有类型,还有左子节点集合和右子节点集合,可以理解为树的根节点。
先调用
ExpressParse#splitWords(String): Word[] 根据定义的 splitWord 进行解析把单词提取出来,分隔符号有:空格、换行、位操作、四则运算、Boolean运算符号、等于、注释符号等等,Word 有行号、列号、index、值属性。
再调用
ExpressParse#(transferWord2ExpressNode(String, Word[]): ExpressNode ,ExpressNode 是带有类型的返回值,这里会根据 Word 的值来判断是什么类型,比如 数字、字符串、boolean、关键字等。NodeTypeManager 中保存了很多关键字,像四则运算符就是关键字。根据 Word 的值和 类型构造 ExpressNode。

到这里还只是单词,还没有树的概念,下面会转为树。

QLPattern#findMatchStatementWithAddRootOptimizeStack(MatchParamsPack,QLPatternNode): QLMatchResult 这个递归方法,根据 pattern 和 nodetype 来进行解析成 QLMatchResultTree,再掉用 QLMatchResultTree#buildExpressNodeTree() 方法进行中序遍历,生成树。

3: 然后调用 ExpressRunner#createInstructionSet(ExpressNode, String): InstructionSet,根据 ExpressNode 中的 NodeType 找到 对应的 InstructionFactory 的实现类,比如 Block、Break、Cast、CallFunction、If、In 等等。
InstructionSet 是指令集的集合,不同的指令,有不同的 excute(RunEnvironment): void 实现方法,比如 GoTo、CloseNewArea、ClearDataStack、CallMacro、Operator。

4: 指令集合生成后,调用 InstructionSetRunner#executeOuter(ExpressRunner, InstructionSet, ExpressLoader,IExpressContext): Object ,调用 InstructionSet#excute(RunEnvironment, InstructionSetContext): CallResult ,调用 InstructionSet#executeInnerOriginInstruction(Runenvironment): void ,把结果生成到 RunEnvironment 中。最后调用 CallResult#getReturnValue(): Object 返回结果。

主要流程: 分隔表达式 -> 转为带有类型的词法 -> 解析词法生成可执行的树 -> 根据树中 nodetype 的pattern 生成 instruction -> 根据不同指令的类型去执行指令。

表达式示例: 10 * 10 + 1 + 2 * 3 + 5 * 2

二. QLPatternNode

模式匹配,即使用 定义好的表达式,去解析传入的字符串

比如这个表达式: “OP_LEVEL4:TYPE=OPERATOR,DEFINE=*|/|mod|%”,name 是 OP_LEVEL4,类型是 运算符,有五种定义,乘、除、mod、取余、和 instassof 。

定义的常量在 KeyWordDefine4Java.nodeTypedefines[] 中。

QLPatternNode.isTreeNode ,是否是根节点,上面的 * 乘法表达式 就是根节点。

QLPatternNode#splitChild() ,把子节点加入到 pattern 中,比如 * QLPatternNode 乘法运算符的 List children 子匹配中,存在 CONST_INTEGER 类型的 QLPatternNode。在递归的时候,会遍历乘法运算符的子 pattern,即整数匹配模式,使用整数匹配模式,匹配乘法前后的数值单词。

在 splitChild() 的时候,根据 nodeTypeDefines 同一个表达式的分隔符的定义,会确定 pattern 的模式。 同一级别的如 加减乘除 就是 OR 模式,而一些函数就是 AND 模式。

三. 构造树

词法分析较为简单,根据传入的表达式内容,按照对应的分隔符进行分隔,然后匹配类型即可。
QLexpress 使用了 findMatchStatementWithAddRootOptimizeStack(MatchParamsPack, QLPatternNode, int point, int deep) 递归函数来进行树的构造。

看递归表达式,应该着眼于 每次递归变化后传递下去的用来保存递归结果的部分

递归表达式中的变量是 QLPatternNode,表达式中,根据 node 的三种 matchMode :DETAIL、AND、OR,进行处理。

OR:遍历 patter.children,寻找合适的词法解析格式。

AND: 也是遍历 pattern.children 但是最后有一些变量的处理和缓存处理

DETAIL:左括号、右括号、注释符、EOF 等使用

递归表达式较为复杂,最终函数的副作用,就是生成了一个树形结构 QLMatchResultTree。

然后在递归表达式的外层,即调用方,拿到树的根节点,即 ExpressNode。

遍历 ExpressNode 的左右子节点,设置其 parent 节点。

把 ExpressNode 转换为 InstructionSet。

createInstructionSetPrivate(InstructionSet, Stack, ExpressNode) ,根据 node 的 type,获取 不同子类 InstructionoFactory,调用 createInstrctionSet(ExpressRunner, InstructionSet) 方法。

跟节点的 ExpressNode 对应的 nodetypekind 是 block,即先调用 BolckInstructionFactory#createInstructionSet(ExpressRunner, InstructionSet),在 block 的 factory 方法中,会遍历所有 children 节点的 nodetypekind 对应的的 factory 方法 ,来创建 instructionSet。

node 获取 children 的顺序是先左边全部,再右边全部。

最终会 return 一个 instructionSet 对象,对象中有个属性是 Instruction[],用来存放 parse 的结果。

四. 执行指令集

调用 InstructionSetRunner#execute(ExpressRunner, InstuctionSet, ExpressLoader, IExpressContext, List,…),先把参数解析封装到 context 中。

       InstructionSetContext  context = OperateDataCacheManager.fetchInstructionSetContext (true,runner,aContext,loader,isSupportDynamicFieldName);

再获取 RunEnvironment,

RunEnvironment environmen = OperateDataCacheManager.fetRunEnvironment(set,(InstructionSetContext) context, isTrace);

最终指令的执行,在 InstructionSet 对象中,

   public void executeInnerOrigiInstruction(RunEnvironment environmen,List<String> errorList,Log aLog) throws Exception{Instruction instruction =null;while (environmen.programPoint < this.instructionList.length) {QLExpressTimer.assertTimeOut();instruction = this.instructionList[environmen.programPoint];instruction.setLog(aLog);// 设置loginstruction.execute(environmen, errorList);}}

一个指令一个执行的执行。

QLexpress源码解析相关推荐

  1. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  2. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

  3. 谷歌BERT预训练源码解析(一):训练数据生成

    目录 预训练源码结构简介 输入输出 源码解析 参数 主函数 创建训练实例 下一句预测&实例生成 随机遮蔽 输出 结果一览 预训练源码结构简介 关于BERT,简单来说,它是一个基于Transfo ...

  4. Gin源码解析和例子——中间件(middleware)

    在<Gin源码解析和例子--路由>一文中,我们已经初识中间件.本文将继续探讨这个技术.(转载请指明出于breaksoftware的csdn博客) Gin的中间件,本质是一个匿名回调函数.这 ...

  5. Colly源码解析——结合例子分析底层实现

    通过<Colly源码解析--框架>分析,我们可以知道Colly执行的主要流程.本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现.(转载请指明出于break ...

  6. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

  7. libev源码解析——定时器原理

    本文将回答<libev源码解析--I/O模型>中抛出的两个问题.(转载请指明出于breaksoftware的csdn博客) 对于问题1:为什么backend_poll函数需要指定超时?我们 ...

  8. libev源码解析——I/O模型

    在<libev源码解析--总览>一文中,我们介绍过,libev是一个基于事件的循环库.本文将介绍其和事件及循环之间的关系.(转载请指明出于breaksoftware的csdn博客) 目前i ...

  9. libev源码解析——调度策略

    在<libev源码解析--监视器(watcher)结构和组织形式>中介绍过,监视器分为[2,-2]区间5个等级的优先级.等级为2的监视器最高优,然后依次递减.不区分监视器类型和关联的文件描 ...

最新文章

  1. 复旦 计算机 学硕 延毕,研究生招考呈现新趋势:非全日制招生遇冷 延期毕业现象越发明显...
  2. NopCommerce 增加 Customer Attributes
  3. linux下imwbr1进程,Linux服务器中木马wnTKYg
  4. java添加不了源代码,JAVA初学者的一些问题
  5. html5 indexeddb 排序,HTML5 IndexedDB,Web SQL数据库和浏览器大战
  6. SpringSecurity案例之认证服务security配置
  7. C语言学习笔记--数组指针和指针数组
  8. CCF202104-1 灰度直方图(100分)【计数】
  9. 《著名企业求职面试指南》——揭秘顺利通过名企面试的“潜规则”
  10. Flex 布局学习笔记
  11. Linux 天翼3G上网
  12. 第三方应用软件检测实验室质量管理体系需要符合哪些要求?
  13. 人工智能资料下载地址分享
  14. node mysql菜鸟教程_Node.js Web 模块
  15. Webpack(上)
  16. 乐吾乐 Topology 全新优化1.0已经内测啦
  17. 项目经理之我思员工能动性
  18. C#使用NPOI的方式操作Excel复制行
  19. 方正平台(企业级应用的开发平台)
  20. vray许可服务器信息无名,【1人回答】vray3.6无法获取许可-3D溜溜网

热门文章

  1. Excel取中间几个字符
  2. Notepad++去掉回车
  3. 【PCB布局布线】之蛇行等长布线(转)
  4. html返回不刷新页面,js有什么办法返回上一个页面并不刷新代码
  5. 【人工智能系列经典图书翻译】可解释机器学习(第二版) 第8章 全局模型无关方法
  6. 空间三角形_七巧板一样的户型,三角形空间改成衣帽间,超实用
  7. 2021-2027全球与中国陶瓷喷雾干燥设备市场现状及未来发展趋势
  8. VxWorks上高精度定时器(auxClk)的配置和使用
  9. 你可能不知道的CAD绘图工具
  10. linux的停止命令