JavaScript实现ZLOGO: 用语法树实现多层循环
照例先上演示弱效果图. 演示地址照旧:
代码如下:
开始 循环4次 循环4次 前进50 左转90度 到此为止 右转90度 到此为止 结束
如上文《JavaScript实现ZLOGO子集: 测试用例》末尾所言, 此文用Antlr进行代码分析生成语法树. 再通过语法树生成p5js绘制代码.
Antlr支持两种代码分析方法, Visitor(监听者)和Visitor(访问者). SO上的问答Antlr4 Listeners and Visitors - which to implement?大致说明了区别. 基于有限的实践, 用Visitor方法生成语法树似乎在实现上更加方便. 尤其相比Creating a simple parser with ANTLR一文中使用监听者+栈来构建语法树.
Antlr生成工具默认不生成Visitor, 添加-visitor参数后可以生成:
java -cp "antlr-4.7-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=JavaScript -visitor 圈3.g4
下面是"定制访问器.js"中构建语法树的部分, 看起来比实现前想的简单. 默认生成的'圈3Visitor'中, visitXX方法实现都是"this.visitChildren(ctx)", 但那样会把所有的子节点返回值放进数组, 形成(至少这里是)多余的层次:
定制访问器.prototype.visit程序 = function(上下文) { 语法树 = {子节点: this.visit(上下文.声明())}; return 语法树; }; 定制访问器.prototype.visit循环 = function(上下文) { return { 类型: '循环', 次数: parseInt(上下文.T数().getText()), 子节点: this.visit(上下文.声明())}; }; 定制访问器.prototype.visit声明 = function(上下文) { return this.visit(上下文.getChild(0)); }; 定制访问器.prototype.visit转向 = function(上下文) { var 方向 = 上下文.T转向().getText(); var 角度 = parseInt(上下文.T数().getText()) * (方向 === "左" ? 1 : -1); return {类型: '转向', 参数: 角度}; }; 定制访问器.prototype.visit前进 = function(上下文) { return {类型: '前进', 参数: parseInt(上下文.T数().getText())}; };
上面的源码生成语法树大致如下所示. 实现上还有很多需要改进的, 比如'前进'和'转向'现在是两种'类型', 但应该是一种; 根节点类型不应为空; 等等:
下面是"编译.js"中基于语法树生成指令列表的方法, 之后就与之前一样根据指令列表生成p5js绘制函数(代码也不用修改).
function 生成指令序列(节点) { var 指令序列 = []; // TODO: 根节点类型不应为空 if (!节点.类型) { var 声明节点 = 节点.子节点; for (var i = 0; i < 声明节点.length; i++) { Array.prototype.push.apply(指令序列, 生成指令序列(声明节点[i])); } } else if (节点.类型 == "循环") { var 指令序列 = []; for (var i = 0; i < 节点.次数; i++) { Array.prototype.push.apply(指令序列, 生成指令序列({子节点: 节点.子节点})); } } // TODO: 修改类型统一为'指令' else if (节点.类型 == "前进" || 节点.类型 == "转向") { return [{名称: (节点.类型 == "前进" ? 常量_指令名_前进 : 常量_指令名_转向), 参数: 节点.参数}]; } return 指令序列; }
修改相应测试用例, 以及清理不再使用的监听器代码后. 代码已从visitor分支(program-in-chinese/quan3)合并到master.
2018-01-02
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java关键字的汉化用词探讨
@狗屎咖啡 的《为GCC添加中文关键字项目》对C关键词进行了汉化. 风格比较简约, 如'if'-如, 'else'-另. 个人感觉在中文编程语言尚未成熟之时, 不妨集思广益, 首先列出一些可选项, 然后从中选出一套或几套风格比较统一的. 这里列出了一些之前归纳的选项. 本文基于此讨论组回复(中文化 C, C++, Objective-C 需要什么样的关键字? · Issue #40 · program-in-chinese/overview)尝试对Java关键词进行探讨. 可惜知乎文章不支持表格, 于是列出如下. 带*的如goto是Java实际并未使用的. 关键词的含义参考List of Java keywords, 加上一些有限的个人理解. 欢迎拍砖, 尤其是带问号的几个. 多谢评论区中各位指摘, 下面有根据评论添加的部分, 恕在下不一一点名感谢了. abstract 抽象 assert*** 确保 断言 boolean 布尔 真假 break 中止 断开 跳出 byte 字节 case 情况 catch 一旦 char 字符 class 类 类型(评论中提到这与'type'含义重复...
- 下一篇
烂尾工程: Java实现的汇编语言编译器
在半年前的《中文编程的尝试历程小记》中简单介绍了这一项目. 由于短期内估计不会继续进行, 而且这个项目好像是至今个人在中文命名实践中的代码量最大的一个项目, 谨在此作一小结. 最新的源码库在program-in-chinese/assembler-in-chinese-experiment. 大致设计草图 以'mov rax 0x1122334455667788'指令示例如下: 当前进度 仅支持两个操作数的部分指令, 第二个操作数仅支持立即数 第一个操作数可以是寄存器,或者简单的内存寻址,如[0] 支持强制类型,如add ax,strict word 5 生成空可执行文件(PE), 尚未填入生成的二进制码 源码结构 下面是所有文件, 希望是一目了然? "分析器类"从单行汇编指令字符串分析生成"代码行类", "汇编器类"从"代码行类"生成二进制码. 其他主要是业务数据描述("模型"包)和功用(utils). 假如要重新继续这一项目, 下面是一些想法: 考虑使用Antlr4, 用类似antlr/grammars-v4的语法文件辅助生成分析器, 省去手动编写分析器 最好有汇编和x64指令背景...
相关文章
文章评论
共有0条评论来说两句吧...