1

PARSERGRAMMAR
プロトコル.g

grammar protocol; 

options {
  language = Java;
  output = AST;
  ASTLabelType=CommonTree;
}

tokens{ 
TRANSITIONS;
PAIR;
}

@header {
package com.javadude.antlr3.x.tutorial;
}

@lexer::header {
  package com.javadude.antlr3.x.tutorial;
}

parse
 : transitions EOF!
   {
     CommonTree root = $transitions.tree;

     int count = root.getChildCount();

     Tree child1 = root.getChild(0);
     Tree child2 = root.getChild(1);
     Tree child3 = root.getChild(2);
     Tree child4 = root.getChild(3);

     System.out.println("root=" + root.getToken().getText() + " has " + count + " child nodes:");
     System.out.println(" - child1=" + child1.toStringTree());
     System.out.println(" - child2=" + child2.toStringTree());
     System.out.println(" - child3=" + child3.toStringTree());
     System.out.println(" - child4=" + child4.toStringTree());
   }
 ;
transitions
 : 'transitions' '=' INT pair+ ';' -> ^(TRANSITIONS INT pair+)
 ;
pair
 : '(' INT ',' INT ')' -> ^(PAIR INT INT)
 ;

INT 
    : ('0'..'9')+;
WHITESPACE
    : ('\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;};

TREEGRAMMARprotocolWalker.g
_

tree grammar protocolWalker;

options {
  language = Java;
  tokenVocab = protocol;   
  ASTLabelType = CommonTree;
}


@header {
package com.javadude.antlr3.x.tutorial;
}

transitions
 : ^(TRANSITIONS INT pair+) 
 {
 System.out.println("transitions=" + $INT.text);
 }
 ;

pair
 : ^(PAIR a=INT b=INT) 
 {
 System.out.println("pair=" + $a.text + ", " + $b.text);

 }
 ;

JAVA TEST RIG
Protocoltest.java

package com.javadude.antlr3.x.tutorial;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
public class Protocoltest {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        //create input stream from standard input
        ANTLRInputStream input = new ANTLRInputStream(System.in);
        //create a lexer attached to that input stream
        protocolLexer lexer = new protocolLexer(input);
        //create a stream of tokens pulled from the lexer
        CommonTokenStream tokens = new CommonTokenStream(lexer);

        //create a parser attached to teh token stream
        protocolParser parser = new protocolParser(tokens);
        //invoke the program rule in get return value
        protocolParser.parse_return r =parser.parse();

        CommonTree t = (CommonTree)r.getTree();
        //output the extracted tree to the console
        System.out.println("\nAST is: " + t.toStringTree());

        //walk resulting tree; create treenode stream first
        CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
        //AST nodes have payloads that point into token stream
        nodes.setTokenStream(tokens);

        //create a tree walker attached to the nodes stream
        protocolWalker walker = new protocolWalker(nodes);

        //invoke the start symbol, rule parse
        walker.transitions();
        }
}

入力

transitions = 3(5,0) (5,1) (5,2);

出力

root=TRANSITIONS has 4 child nodes:
 - child1=3
 - child2=(PAIR 5 0)
 - child3=(PAIR 5 1)
 - child4=(PAIR 5 2)

AST is: (TRANSITIONS 3 (PAIR 5 0) (PAIR 5 1) (PAIR 5 2))
pair=5, 0
pair=5, 1
pair=5, 2
transitions=3  

問題
上記のように、パーサー文法(protocol.g)で、遷移ルートのすべての子をchild1、child2、child3、およびchild4として格納できます。また、これらを印刷しました。ツリー文法で、これらをどのように保存し、これらに対して操作を実行できますか?ありがとうございました

4

1 に答える 1

1

Javaクラスをインスタンス化します(Javaオブジェクトを作成します)。たとえば、ツリーの最初の数字は、作成されるオブジェクトの数を決定します。次に、PAIR 5 0は、2つの引数(5,0)、PAIR5を持つオブジェクトを作成します。 1は2つの引数(5,1)を持つ2番目のオブジェクトを作成し、PAIR 5 2は2つの引数(5,2)を持つ3番目のオブジェクトを作成します。

これは、トランジションを作成してペアを追加する簡単な方法であり、にわずかな変更を加えるだけで済みprotocolWalker.gます。ただし、最初に、使用するダミークラスTransitionsPairクラスを次に示します。

Transitions.java

import java.util.ArrayList;


public class Transitions {
    private ArrayList<Pair> pairs = new ArrayList<Pair>();

    public void addPair(Pair pair){
        System.out.println(String.format("Added pair %s to transitions", pair));
        pairs.add(pair);
    }

    @Override
    public String toString() {
        return "Pairs: " + pairs;
    }
}

Pair.java

public class Pair {
    private int a;
    private int b;

    public Pair(int a, int b){
        this.a = a;
        this.b = b;
    }

    @Override
    public String toString() {
        return String.format("(%d, %d)", a, b);
    }
}

これが変更されたprotocolWalker.gです。

protocolWalker.g(変更済み)

tree grammar protocolWalker;

options {
  language = Java;
  tokenVocab = protocol;   
  ASTLabelType = CommonTree;
}    


@header {
    package com.javadude.antlr3.x.tutorial;
    import java.util.List;
    import java.util.ArrayList;
}

@members { 
  //stores all the transitions objects as they get processed
  private ArrayList<Transitions> allTransitions = new ArrayList<Transitions>();

  //returns all the transitions
  public List<Transitions> getAllTransitions() { 
    return allTransitions;
  }
}


transitions
@init { 
        //create a Transitions object when the rule is hit
        Transitions transitions = new Transitions();

        //store it to be accessed later.
        allTransitions.add(transitions);
      } 
 : ^(TRANSITIONS INT transitions_pair[transitions]+) //pass the object to transitions_pair for each PAIR encountered
 {
     System.out.println("transitions=" + $INT.text);
 }
 ;

transitions_pair[Transitions transitions]
 : ^(PAIR a=INT b=INT) 
 {
     System.out.println("pair=" + $a.text + ", " + $b.text);
     //make a call to the Transitions object that was passed to this rule.
     transitions.addPair(new Pair($a.int, $b.int));
 }
 ;

(ルールがtransitions-buildingに関連付けられているため、名前を変更pairしましtransitions_pairた。)ルールはをtransitions呼び出し、同時にtransitions_pair新しいオブジェクトを渡します。受信したオブジェクトに新しいオブジェクトを追加します。Transitionstransitions_pairPairTransitions

ツリーパーサーとトークンパーサーのルールは、[ArgType argname,...]ウェイを使用してオブジェクトを受け入れるように記述できます。この場合、子PAIRツリーに簡単にアクセスできます。

Protocoltest.java保存されたトランジションを印刷するために、に小さな変更を追加しました。

        ...
        //invoke the start symbol, rule parse
        walker.transitions();

        //get the stored transitions and print them out.            
        List<Transitions> transitions = walker.getAllTransitions();
        System.out.println(transitions);
        ...

ウォーカーの新しい出力は次のとおりです。

pair=5, 0
Added pair (5, 0) to transitions
pair=5, 1
Added pair (5, 1) to transitions
pair=5, 2
Added pair (5, 2) to transitions
transitions=3
[Pairs: [(5, 0), (5, 1), (5, 2)]]

これが私が行った主な変更の要約です:

  • ウォーカーからのトランジションを保存して返す方法を追加しました。
  • Transitionsルールにオブジェクトを作成するためのコードを追加しましたtransitions
  • オブジェクトをに渡すコードを追加しましたtransitions_pair
  • ウォーカーからトランジションを取得して印刷するためのコードをテスターに​​追加しました。

自分のTransitionsクラスを実装すれば、すべて準備が整うと思います。

于 2012-10-31T09:04:08.383 に答える