3

いくつかのjavascriptコードで解析ツリーを生成して使用できるように、antlr3APIを理解するのに問題があります。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は、フラットな1次元のトークンストリームを作成します。

ANTLRWorksは、ソースを解釈するときに、その場で独自の解析ツリーを作成します。このツリーにアクセスすることはできません(Javascriptを使用したり、Javaを使用したりすることはできません)。(サブ)ツリーのルートであると思われるトークンを定義するか、ASTから削除する必要のあるトークンを定義する必要があります。適切なASTを作成する方法を説明する次のQ&Aをチェックしてください:ANTLRを使用して構築されたASTを出力する方法は?

編集

SOにはまだ適切なJavaScriptデモがないため、ここに簡単なデモがあります。

次の文法は、次の演算子を使用してブール式を解析します。

  • また
  • いいえ

優先順位が最も高い場所not

もちろん、とがtrueあり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を生成します。

ファイル: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

次に、レクサー、パーサー、ツリーウォーカーを生成します。

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 に答える