5

簡単な例:

(grammar):

stat: ID '=' expr NEWLINE -> ^('=' ID expr)

expr: atom '+' atom -> ^(+ atom atom)

atom: INT | ID

...

(input text): a = 3 + 5

'3 + 5'に対応するCommonTreeには、'+'トークンと2つの子(3、5)が含まれています。

この時点で、このツリー( '3 + 5')に解析された元の入力テキストを復元するための最良の方法は何ですか?

オブジェクト内の個々のトークンのテキスト、位置、および行番号を取得しているCommonTreeので、理論的には、空白トークンのみを破棄し、この情報を使用してそれらをつなぎ合わせることができますが、エラーが発生しやすいように見えます。

これを行うためのより良い方法はありますか?

4

2 に答える 2

3

これを行うためのより良い方法はありますか?

よくわかりません。もちろん、別の方法があります。あなたは何が良いかを決定します。

別のオプションは、カスタムASTノードクラス(および対応するノードアダプター)を作成し、解析中に一致したテキストをこのASTノードに追加することです。ここでの秘訣はskip()、レクサーからトークンを破棄するを使用せずに、それをHIDDENチャネルに配置することです。これは事実上同じですが、これらの(非表示の)トークンが一致するテキストはパーサーで引き続き使用できます。

簡単なデモ:これら3つのファイルすべてを次の名前のディレクトリに配置しますdemo

デモ/Tg

grammar T;

options {
  output=AST;
  ASTLabelType=XTree;
}

@parser::header {
  package demo;
  import demo.*;
}

@lexer::header {
  package demo;
  import demo.*;
}

parse
 : expr EOF -> expr
 ;

expr
@after{$expr.tree.matched = $expr.text;}
 : Int '+' Int ';' -> ^('+' Int Int)
 ;

Int
 : '0'..'9'+
 ;

Space
 : ' ' {$channel=HIDDEN;}
 ;

demo / XTree.java

package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class XTree extends CommonTree {

  protected String matched;

  public XTree(Token t) {
    super(t);
    matched = null;
  }
}

demo / Main.java

package demo;

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class Main {

  public static void main(String[] args) throws Exception {
    String source = "12    +  42 ;";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.setTreeAdaptor(new CommonTreeAdaptor(){
      @Override
      public Object create(Token t) {
        return new XTree(t);
      }
    }); 
    XTree root = (XTree)parser.parse().getTree();
    System.out.println("tree    : " + root.toStringTree());
    System.out.println("matched : " + root.matched);    
  }
}

このデモを実行するには、シェルを開いて、ディレクトリを保持しているディレクトリにcdしdemo、次のコマンドを実行します。

java -cp demo / antlr-3.3.jar org.antlr.Tool demo / Tg
javac -cp demo / antlr-3.3.jar demo/*。java
java -cp。:demo / antlr-3.3.jar demo.Main

これにより、次の出力が生成されます。

ツリー:(+ 12 42)
一致:12 + 42;
于 2012-10-17T20:27:28.563 に答える
0

別の可能性は、TokenRewriteStreamいくつかのtoString()方法があるを使用することです。

@BartKiersの例Demo/Main.javaから借用するには

TokenRewriteStream tokens = new TokenRewriteStream(lexer)
TParser parser = new TParser(tokens);
...
tokens.toString(n.getTokenStartIndex(), n.getTokenStopIndex() + 1).trim()

したがって、解析ツリーのノード'n'が与えられた場合、上記のようにそのノードでtoString()を呼び出すと、このノードを「生成」した文字列が生成されます。

于 2016-12-13T20:10:16.003 に答える