參考: "ANTLR4: Making a compiler with the JavaScript runtime" 演示效果雖弱, 還是先上圖吧: 線上演示: "地址" . 源碼庫: "program in chinese/quan4" 下載到本地後在瀏覽器中打開"圈4.html"就可以在本地試 ...
參考: ANTLR4: Making a compiler with the JavaScript runtime
演示效果雖弱, 還是先上圖吧:
線上演示: 地址.
下載到本地後在瀏覽器中打開"圈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://stackoverflow.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