antlr3-生成解析树 [英] antlr3 - Generating a Parse Tree

查看:97
本文介绍了antlr3-生成解析树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在弄清antlr3 API时遇到了麻烦,因此我可以在一些javascript代码中生成并使用解析树.当我使用antlrWorks(其IDE)打开语法文件时,解释器可以向我显示语法分析树,它甚至是正确的.

I'm having trouble figuring out the antlr3 API so I can generate and use a parse tree in some javascript code. When I open the grammar file using antlrWorks (their IDE), the interpreter is able to show me the parse tree, and it's even correct.

在使用antlr3运行时在我的代码中跟踪如何获取此解析树的资源方面,我遇到了很多困难.我一直在弄乱运行时文件和解析器文件中的各种功能,但无济于事:

I'm having a lot of difficulties tracking down resources on how to get this parse tree in my code using the antlr3 runtime. I've been messing around with the various functions in the runtime and Parser files but to no avail:

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会自动从语法文件生成解析树,因此我假设我可以使用一些运行时函数来访问此基本解析树我可能不知道.我的想法正确吗?

Since antlrWorks can display the parse tree without any tree grammar from myself, and since I have read that antlr automatically generates a parse tree from the grammar file, I'm assuming that I can access this basic parse tree with some runtime functions that I am probably not aware of. Am I correct in this thinking?

推荐答案

HugeAntlrs写道:

由于antlrWorks可以显示解析树而没有我自己的任何树语法,并且由于我已阅读到antlr会自动从语法文件生成解析树,因此我假设我可以使用一些运行时函数来访问此基本解析树我可能不知道.我的想法正确吗?

Since antlrWorks can display the parse tree without any tree grammar from myself, and since I have read that antlr automatically generates a parse tree from the grammar file, I'm assuming that I can access this basic parse tree with some runtime functions that I am probably not aware of. Am I correct in this thinking?

不,那是不正确的. ANTLR创建一个统一的一维令牌流.

No, that is incorrect. ANTLR creates a flat, 1 dimensional stream of tokens.

ANTLRWorks在解释某些源时会动态创建自己的解析树.您无权访问此树(不支持Java甚至不支持Java).您将必须定义您认为应该是(子)树根的令牌和/或定义需要从AST中删除的令牌.请查看下面的问答,其中介绍了如何创建正确的AST:如何输出使用ANTLR构建的AST?

ANTLRWorks creates its own parse tree on the fly when interpreting some source. You have no access to this tree (not with Javascript or even with Java). You will have to define the tokens that you think should be the roots of your (sub) trees and/or define the tokens that need to be removed from your AST. Checkout the following Q&A that explains how to create a proper AST: How to output the AST built using ANTLR?

由于尚无适当的JavaScript演示,因此这里是一个快速演示.

Since there's no proper JavaScript demo on SO yet, here's a quick demo.

以下语法使用以下运算符解析布尔表达式:

The following grammar parses boolean expression with the following operators:

  • 不是

其中not具有最高优先级.

当然有truefalse,并且可以使用括号将表达式分组.

Of course there are true and false, and the expressions can be grouped using parenthesis.

grammar Exp;

options {
  output=AST;
  language=JavaScript;
}

parse
  :  exp EOF -> exp
  ;

exp
  :  orExp
  ;

orExp
  :  andExp (OR^ andExp)*
  ;

andExp
  :  eqExp (AND^ eqExp)*
  ;

eqExp
  :  unaryExp (IS^ unaryExp)*
  ;

unaryExp
  :  NOT atom -> ^(NOT atom)
  |  atom
  ;

atom
  :  TRUE
  |  FALSE
  |  '(' exp ')' -> exp
  ;

OR     : 'or' ;
AND    : 'and' ;
IS     : 'is' ;
NOT    : 'not' ;
TRUE   : 'true' ;
FALSE  : 'false' ;
SPACE  : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;

上面的语法产生一个AST,可以将该AST馈送到下面的树行者:

The grammar above produces an AST which can be fed to the tree-walker below:

tree grammar ExpWalker;

options {
  tokenVocab=Exp;
  ASTLabelType=CommonTree;
  language=JavaScript;
}

// `walk` returns a string
walk returns [expr]
  :  exp {expr = ($exp.expr == 1) ? 'True' : 'False';}
  ;

// `exp` returns either 1 (true) or 0 (false)
exp returns [expr]
  :  ^(OR  a=exp b=exp) {expr = ($a.expr == 1 || $b.expr == 1) ? 1 : 0;}
  |  ^(AND a=exp b=exp) {expr = ($a.expr == 1 && $b.expr == 1) ? 1 : 0;}
  |  ^(IS  a=exp b=exp) {expr = ($a.expr == $b.expr) ? 1 : 0;}
  |  ^(NOT a=exp)       {expr = ($a.expr == 1) ? 0 : 1;}
  |  TRUE               {expr = 1;}
  |  FALSE              {expr = 0;}
  ;

(对{ ... }中凌乱的JavaScript代码表示歉意:我对JavaScript的使用经验很少!)

(apologies for the messy JavaScript code inside { ... }: I have very little experience with JavaScript!)

现在下载ANTLR 3.3(没有更早的版本!)和JavaScript运行时文件:

Now download ANTLR 3.3 (no earlier version!) and the JavaScript runtime files:

  • http://www.antlr.org/download/antlr-3.3-complete.jar
  • http://www.antlr.org/download/antlr-javascript-runtime-3.1.zip

antlr-3.3-complete.jar重命名为antlr-3.3.jar并解压缩antlr-javascript-runtime-3.1.zip,并将所有文件存储在与Exp.gExpWalker.g文件相同的文件夹中.

Rename antlr-3.3-complete.jar to antlr-3.3.jar and unzip antlr-javascript-runtime-3.1.zip and store all files in the same folder as your Exp.g and ExpWalker.g files.

现在生成词法分析器,解析器和tree-walker:

Now generate the lexer, parser and tree-walker:


java -cp antlr-3.3.jar org.antlr.Tool Exp.g 
java -cp antlr-3.3.jar org.antlr.Tool ExpWalker.g

并使用以下html文件对其进行全部测试:

And test it all with the following html file:

<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>

观察结果:

这篇关于antlr3-生成解析树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆