3

我无法弄清楚 antlr3 API,因此我可以在一些 javascript 代码中生成和使用解析树。当我使用 antlrWorks(他们的 IDE)打开语法文件时,解释器能够向我显示解析树,它甚至是正确的。

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

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

4

1 回答 1

7

HugeAntlrs 写道:

由于 antlrWorks 可以在没有我自己的任何树语法的情况下显示解析树,并且由于我已经阅读了 antlr 自动从语法文件生成解析树,所以我假设我可以使用一些运行时函数访问这个基本的解析树。大概不知道。我的这种想法正确吗?

不,这是不正确的。ANTLR 创建一个平面的一维令牌流。

ANTLRWorks 在解释某些源时动态创建自己的解析树。您无权访问此树(不能使用 Javascript 甚至 Java)。您必须定义您认为应该是(子)树根的标记和/或定义需要从 AST 中删除的标记。查看以下解释如何创建正确 AST 的问答:如何输出使用 ANTLR 构建的 AST?

编辑

由于在 SO 上还没有合适的 JavaScript 演示,这里有一个快速演示。

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

  • 或者
  • 不是

其中not优先级最高。

当然还有trueand false,并且可以使用括号对表达式进行分组。

文件:Exp.g

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,它可以被提供给下面的 tree-walker:

文件:ExpWalker.g

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 的经验很少!)

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

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

现在生成词法分析器、解析器和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 文件对其进行测试:

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

看看结果:

在此处输入图像描述

于 2011-05-12T18:14:58.723 回答