antlr3-生成解析树
我很难理解ANTLR3API,因此我无法在一些javascript代码中生成并使用解析树。当我使用antlrWorks(他们的IDE)打开语法文件时,解释器能够向我显示解析树,甚至是正确的 在如何使用antlr3运行时在代码中获取此解析树方面,我在跟踪资源方面遇到了很多困难。我一直在乱搞运行时和解析器文件中的各种函数,但都没有用:antlr3-生成解析树,antlr,antlr3,antlrworks,parse-tree,Antlr,Antlr3,Antlrworks,Parse Tree,我很难理解ANTLR3API,因此我无法在一些javascript代码中生成并使用解析树。当我使用antlrWorks(他们的IDE)打开语法文件时,解释器能够向我显示解析树,甚至是正确的 在如何使用antlr3运行时在代码中获取此解析树方面,我在跟踪资源方面遇到了很多困难。我一直在乱搞运行时和解析器文件中的各种函数,但都没有用: var input = "(PR=5000)", cstream = new org.antlr.runtime.ANTLRStringStream(input),
var input = "(PR=5000)",
cstream = new org.antlr.runtime.ANTLRStringStream(input),
lexer = new TLexer(cstream),
tstream = new org.antlr.runtime.CommonTokenStream(lexer),
parser = new TParser(tstream);
var tree = parser.query().tree;
var nodeStream = new org.antlr.runtime.tree.CommonTreeNodeStream(tree);
nodeStream.setTokenStream(tstream);
parseTree = new org.antlr.runtime.tree.TreeParser(nodeStream);
由于antlrWorks可以显示解析树,而不需要我自己提供任何树语法,而且我已经了解到antlr会从语法文件自动生成解析树,因此我假设我可以使用一些可能不知道的运行时函数访问此基本解析树。我的想法正确吗
Hugeantls写道:
由于antlrWorks可以显示解析树,而不需要我自己提供任何树语法,而且我已经了解到antlr会从语法文件自动生成解析树,因此我假设我可以使用一些可能不知道的运行时函数访问此基本解析树。我的想法正确吗
不,那是不正确的。ANTLR创建一个平面的一维令牌流
ANTLRWorks在解释某些源代码时会动态创建自己的解析树。您无法访问此树(不使用Javascript,甚至不使用Java)。您必须定义您认为应该是(子)树的根的标记和/或定义需要从AST中删除的标记。检查以下问答,说明如何创建正确的AST:
编辑
由于目前还没有合适的JavaScript演示,下面是一个快速演示
以下语法使用以下运算符分析布尔表达式:
- 或
- 及
- 是
- 不是
not
具有最高优先级
当然有true
和false
,表达式可以使用括号分组
文件:Exp.g
上面的语法生成一个AST,可以将其馈送到下面的树行者:
文件:ExpWalker.g
(为{…}
中凌乱的JavaScript代码道歉:我对JavaScript几乎没有经验!)
现在下载ANTLR 3.3(无早期版本!)和JavaScript运行时文件:
antlr-3.3-complete.jar
为antlr-3.3.jar
并解压缩antlr-javascript-runtime-3.1.zip
并将所有文件存储在与Exp.g
和ExpWalker.g
文件相同的文件夹中
现在生成lexer、parser和tree walker:
java -cp antlr-3.3.jar org.antlr.Tool Exp.g
java -cp antlr-3.3.jar org.antlr.Tool ExpWalker.g
java-cp antlr-3.3.jar org.antlr.Tool Exp.g
java-cp antlr-3.3.jar org.antlr.Tool ExpWalker.g
并使用以下html文件进行测试:
<html>
<head>
<script type="text/javascript" src="antlr3-all-min.js"></script>
<script type="text/javascript" src="ExpLexer.js"></script>
<script type="text/javascript" src="ExpParser.js"></script>
<script type="text/javascript" src="ExpWalker.js"></script>
<script type="text/javascript">
function init() {
var evalButton = document.getElementById("eval");
evalButton.onclick = evalExpression;
}
function evalExpression() {
document.getElementById("answer").innerHTML = "";
var expression = document.getElementById("exp").value;
if(expression) {
var lexer = new ExpLexer(new org.antlr.runtime.ANTLRStringStream(expression));
var tokens = new org.antlr.runtime.CommonTokenStream(lexer);
var parser = new ExpParser(tokens);
var nodes = new org.antlr.runtime.tree.CommonTreeNodeStream(parser.parse().getTree());
nodes.setTokenStream(tokens);
var walker = new ExpWalker(nodes);
var value = walker.walk();
document.getElementById("answer").innerHTML = expression + " = " + value;
}
else {
document.getElementById("exp").value = "enter an expression here first";
}
}
</script>
</head>
<body onload="init()">
<input id="exp" type="text" size="35" />
<button id="eval">evaluate</button>
<div id="answer"></div>
</body>
</html>
函数init(){
var evalButton=document.getElementById(“eval”);
evalButton.onclick=evalExpression;
}
函数evalExpression(){
document.getElementById(“答案”).innerHTML=“”;
var表达式=document.getElementById(“exp”).value;
if(表达式){
var lexer=newexplexer(neworg.antlr.runtime.ANTLRStringStream(表达式));
var tokens=neworg.antlr.runtime.CommonTokenStream(lexer);
var parser=新的ExpParser(令牌);
var nodes=new org.antlr.runtime.tree.CommonTreeNodeDestream(parser.parse().getTree());
nodes.setTokenStream(令牌);
var walker=新的ExpWalker(节点);
var值=walker.walk();
document.getElementById(“answer”).innerHTML=表达式+“=”+值;
}
否则{
document.getElementById(“exp”).value=“首先在此处输入表达式”;
}
}
评价
看看结果:
非常感谢您的解释。这为我澄清了antlr内部的许多误解。最后,我将尝试使用另一个解析器生成器Jison,因为它是nodejs的本机。再次感谢@Hugeantls,Jison看起来不错,我去看看。谢谢您可能还想退房。 java -cp antlr-3.3.jar org.antlr.Tool Exp.g java -cp antlr-3.3.jar org.antlr.Tool ExpWalker.g
<html>
<head>
<script type="text/javascript" src="antlr3-all-min.js"></script>
<script type="text/javascript" src="ExpLexer.js"></script>
<script type="text/javascript" src="ExpParser.js"></script>
<script type="text/javascript" src="ExpWalker.js"></script>
<script type="text/javascript">
function init() {
var evalButton = document.getElementById("eval");
evalButton.onclick = evalExpression;
}
function evalExpression() {
document.getElementById("answer").innerHTML = "";
var expression = document.getElementById("exp").value;
if(expression) {
var lexer = new ExpLexer(new org.antlr.runtime.ANTLRStringStream(expression));
var tokens = new org.antlr.runtime.CommonTokenStream(lexer);
var parser = new ExpParser(tokens);
var nodes = new org.antlr.runtime.tree.CommonTreeNodeStream(parser.parse().getTree());
nodes.setTokenStream(tokens);
var walker = new ExpWalker(nodes);
var value = walker.walk();
document.getElementById("answer").innerHTML = expression + " = " + value;
}
else {
document.getElementById("exp").value = "enter an expression here first";
}
}
</script>
</head>
<body onload="init()">
<input id="exp" type="text" size="35" />
<button id="eval">evaluate</button>
<div id="answer"></div>
</body>
</html>