照例先上演示弱效果图. 演示地址照旧:

代码如下:

开始循环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 JavaScript实现ZLOGO: 用语法树实现多层循环...相关推荐

  1. Delphi及C++Builder经典图书一览表(持续更新中2018.01.02)

    序号 书名 原版书名 作者 译者 出版社 页数 年代 定价 备注 1 C++Builder 5程序设计大全 C++Builder 5 Developer's Guide Jarrod Hollingw ...

  2. 2018/01/22 爬虫日记

    20171024 ①导入自定义的模块(如类),需要在当前类作导入 类的引用声明,如self.tool = tool.Tool() 20171025 ①正则表达式:两个<><>之 ...

  3. javaScript系列 [02]-javaScript对象探析

    [02]-javaScript对象探析 题记:多年前,以非常偶然的方式关注了微信公众号"面向对象",本以为这个公众号主要以分享面向对象编程的干货为主,不料其乃实实在在的猿圈相亲平台 ...

  4. 2018.01.21.一周机器学习周记

    时间:2018.01.21.一周 主要内容 1.整理前期关于决策树的一个小型实践项目文档(实践进行中) 2.搭建TensorFlow环境(进行中) 3.拓展:实践Python的自动化模块pyautog ...

  5. js日期格式判断(2018/01/30) -方法 小时分秒格式判断((HH:MM)

    案例如下: //日期格式判斷         function lo_isDatePart(dateStr) {             var parts;             if (date ...

  6. 2017-12-09 JavaScript实现ZLOGO子集: 测试用例

    续前文JavaScript实现ZLOGO子集: 前进+转向. 在添加新功能之前, 先添加测试用例, 以应对日益复杂的代码. 选择使用QUnit编写运行测试用例. 暂时对比较复杂和I/O无关的部分进行测 ...

  7. javaweb(02) JavaScript基础知识

    javaweb(02): JavaScript基础知识 JavaScript简介 为什么出现JavaScript Javascript是什么 JavaScript和Java的关系? 就像卡巴斯基和巴基 ...

  8. 《安富莱嵌入式周报》第246期:2021.12.27--2022.01.02

    往期周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - P ...

  9. 【模型】【课程笔记】01+02+03 金融风险管理导论

    本文为课程<金融风险管理>第1-3章学习笔记,用于知识点总结和复习,对应教材<Quantitative Risk Management(2015)>,标号为原版书公式以便查阅. ...

最新文章

  1. 一块GPU就能训练语义分割网络,百度PaddlePaddle是如何优化的?
  2. 【加密解密】单表加密(Javascript实现)
  3. 职业生涯的8种德---非常重要
  4. ASP.NET把DataTable转成XML文件的函数
  5. .net redis定时_一场由fork引发的超时,让我们重新探讨Redis的抖动问题
  6. 16. GD32F103C8T6入门教程-adc 使用教程2-dma+连续扫描方式采集数据
  7. 一个 JVM 参数引发的频繁 CMS GC
  8. 【android studio】解决android studio drawable新建项目时只有一个drawable目录的问题
  9. 【SAS BASE】PROC SORT
  10. Java基础之continue与break区别
  11. Echarts图表没数据的时候,用图片代替暂无数据(图片自适应)
  12. 存储型路由器和SAN路由器
  13. Winform:自定义滚动条——可自定义皮肤
  14. Blender2.8基础四:手绘贴图篇
  15. 欧科云链链上卫士:做穿越Web3黑暗森林的那盏探照灯
  16. Ubuntu Kylin 20_10 在VMware Workstation Pro上安装
  17. 分享130个中国风PPT模板,总有一款适合你
  18. 电商产品展示,选360°全景还是3D展示?
  19. 程序猿面试题:为什么曹操能号令诸侯?
  20. python表达式_Python-计算字符串中的数学表达式

热门文章

  1. B站up主硬核打造「螃蟹火星车」,遥控、拍照、测距,还能做人脸检测;网友:赛博螃克...
  2. AutoX无人车完成1亿美元A轮融资,东风汽车领投,阿里旗下基金入股
  3. 全球首款碳纳米管通用计算芯片问世!RISC-V架构,5倍于摩尔定律,Nature连发三文推荐...
  4. 腾讯极客攻破iPhone刷脸解锁,凭一副眼镜,转走熟睡用户的钱
  5. 8亿参数,刷新ImageNet纪录:何恺明团队开源最强ResNeXt预训练模型
  6. 云安全云计算 迷团大揭幕
  7. 《C++面向对象高效编程(第2版)》——3.13 采用语义
  8. 6426C Lab6 部署和配置RMS
  9. node.js入门 - 2.创建一个简单聊天室
  10. 去掉微软认证的WINDOWS盗版标志