欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

2017-12-02 编程语言试验之Antlr4+JavaScript实现"圈4"

程序员文章站 2022-12-29 15:29:17
参考: "ANTLR4: Making a compiler with the JavaScript runtime" 演示效果虽弱, 还是先上图吧: 在线演示: "地址" . 源码库: "program in chinese/quan4" 下载到本地后在浏览器中打开"圈4.html"就可以在本地试 ......

参考: antlr4: making a compiler with the javascript runtime

演示效果虽弱, 还是先上图吧:
2017-12-02 编程语言试验之Antlr4+JavaScript实现"圈4"

在线演示: .

源码库:

下载到本地后在浏览器中打开"圈4.html"就可以在本地试验.

以后设计实现好语言后可以直接用静态网页作在线编程的演示, 觉得还蛮有用.

注: js代码中各种不良操作(比如全局函数定义). 请勿作为js学习材料使用. 与前文一样, 此文的目标不是一个实用的编程语言.

语法非常简单(圈4.g4), 只为演示之用. 前文编程语言试验之antlr4+java实现"圈2"有更多格式的解释:

grammar 圈4;
程序   : 求约数;

求约数    : '求约数' t数 ;

t数 : [0-9]+ ;
t空白     : [ \n\t]+ -> skip;

下面命令生成词法语法分析器相关javascript文件(圈4.tokens, 圈4lexer.js, 圈4lexer.tokens, 圈4listener.js, 圈4parser.js):

$ java -cp "antlr-4.7-complete.jar:$classpath" org.antlr.v4.tool -dlanguage=javascript 圈4.g4

作为解释器的"定制监听器.js":

var antlr4 = require('antlr4/index');
const 圈4listener = require('./圈4listener.js').圈4listener

定制监听器 = function () {
  圈4listener.call(this);
  return this;
}

定制监听器.prototype = object.create(圈4listener.prototype);
定制监听器.prototype.constructor = 定制监听器;
/*
无需接口定义: enter程序/exit程序/enter求约数
*/
定制监听器.prototype.exit求约数 = function(上下文) {
  var 原数 = parseint(上下文.getchild(1).gettext());
  document.getelementbyid("输出").innerhtml = 原数 + "的约数: " + 求约数(原数);
};

function 求约数(原数) {
  var 约数 = [];
  for (var i = 1; i < 原数 - 1; i++) {
    if (原数 % i == 0) {
      约数.push(i);
    }
  }
  return 约数;
}

exports.定制监听器 = 定制监听器;

读取文件输入, 调用附着了定制监听器的分析器"代码分析.js":

const antlr4 = require("antlr4/index")
const 圈4lexer = require("./圈4lexer.js")
const 圈4parser = require("./圈4parser.js")
const 定制监听器 = require("./定制监听器.js").定制监听器

运行();

// todo: 需改进-现为全局, 由于browserify
function 运行() {
  var 代码 = document.getelementbyid('输入代码').value;
  var 输入流 = new antlr4.inputstream(代码)
  var 词法分析器 = new 圈4lexer.圈4lexer(输入流)
  var 词 = new antlr4.commontokenstream(词法分析器)
  var 语法分析器 = new 圈4parser.圈4parser(词)
  语法分析器.buildparsetrees = true

  antlr4.tree.parsetreewalker.default.walk(new 定制监听器(), 语法分析器.程序())
}

window.运行 = 运行;

html界面"圈4.html":

<html>
  <head>
    <!-- defer原因: https://*.com/a/26077148/1536803 不然需要document.ready判断 -->
    <script src="圈4.js" defer></script>
  </head>
  <body>
    <textarea id="输入代码">求约数50
    </textarea>
    <button onclick="运行()">运行</button> 
    <span id="输出"></span>
  </body>
</html>

是的, 上面的"圈4.js"需要另行生成. 安装browserify后运行:

$ browserify 代码分析.js > 圈4.js