2009-11-24 33 views
6

Bazı metin IDE benzeri işlevler için Antlr kullanmaya çalışıyorum - özellikle kod katlama noktalarını tanımlamak ve sözdizimi vurgulama uygulamak için bir dosyayı ayrıştırma.Ağaçları ANTLR'de anlama

İlk soru - Antlr bu gereksinime uygun mu, yoksa aşırı mı? Bu ,, regex ve/veya el-rolled ayrıştırıcı kullanılarak elde edilebilir ... ama bu benim için bu işi yapmak için orada Antlr var gibi görünüyor.

Mükemmel bir eğitim kaynağı olan here'u inceledim.

Bir Java dilbilgisi oluşturmayı (standard grammar'u kullanarak) almayı ve her şeyin düzgün bir şekilde bir ağaca ayrılmasını sağladım. Ancak, ağacın içinde yuvalanmış öğeleri görmeyi beklerdim. Aslında, her şey en üstteki elemanın bir çocuğu.

Ör. Verilen: Ben paket ilanı için düğüm, bir çocuk olmak Foo için ağaç düğümü beklerdim

package com.example 
public class Foo { 
    String myString = "Hello World" 
    // etc 
} 

. Aynı şekilde, myString Foo'nun bir çocuğu olurdu. Bunun yerine, Foo ve myString (ve bu konuyla ilgili diğer her şey) öğesinin tümü package'un çocuklarıdır.

public void init() throws Exception { 
    CharStream c = new ANTLRFileStream(
      "src/com/inversion/parser/antlr/Test.code"); 

    Lexer lexer = new JavaLexer(c); 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    JavaParser parser = new JavaParser(tokens); 
    parser.setTreeAdaptor(adaptor); 

    compilationUnit_return result = parser.compilationUnit(); 
} 

static final TreeAdaptor adaptor = new CommonTreeAdaptor() { 
    public Object create(Token payload) { 
     if (payload != null) 
     { 
      System.out.println("Create " + JavaParser.tokenNames[payload.getType()] + ": L" + payload.getLine() + ":C" + payload.getCharPositionInLine() + " " + payload.getText()); 
     } 
     return new CommonTree(payload); 
    } 
}; 

result.getTree() döner Çocukları ayrıştırma sonucudur bir CommonTree örneği, incelenmesi:

İşte ayrıştırılmasını yapıyor alakalı alıntı bu. (Belki de yanlış)

Beklenen değer

package com.example (4 tokens) 
    | 
    +-- public class Foo (3 tokens) 
     | 
     +--- String myString = "Hello World" (4 tokens) 
     +--- Comment "// etc" 

(veya benzeri)

Gerçek değer

package 
com 
. 
example 
public 
class 
Foo 
String 
myString 
= 
"Hello World" 
(Tüm değerler result.getTree() kök düğümün çocukları olan)

Bunun nasıl çalışması gerektiğine dair bir anlayışım var mı?

Şu ana kadar Antlr'de tam bir noob var ve öğrenme eğrisini oldukça dik buluyorum.

+0

Ağacı, bulduğunuz şekilde ve ağacı beklediğiniz gibi gösterir misiniz? – Svante

+3

Bu arada, normal olmayan dilleri ayrıştırma normal ifadelerle gerçekleştirilemez. "Ağaç", "özyinelemeli" veya "iç içe" gördüğünüzde, "regeekssiz" düşünün. – Svante

+0

@Svante - Tabii - Ben postada beklenen vs gerçek genişledim. Bu yardımcı olur umarım. –

cevap

6

antlr.org üzerine dosya paylaşım bölümünün üst kısmında Java 6 dilbilgisi ağaç binayı içermez. İki şey yapman gerekecek.Öncelikle, bir AST kurmak istiyorum antlr söyle:

options { 
    output=AST; 
} 

İkinci, ağaç ağaç operatörlerini kullanarak ya ya kuralları yeniden kullanarak nasıl görünmesi gerektiği söylemek gerekir. documentation on tree construction'a bakın. Genelde her ikisinin bir kombinasyonunu yapıyorum.

1

Ağaç oluşturmak için, çıktı = AST'yi ayarlamanız gerekir. (Özet söz dizimi ağacı)

Bildiğim kadarıyla, ANTLR'de yalnızca 1 jeton bir ağacın kökü olabilir, bu nedenle tam olarak aradığınız şeyi alamazsınız, ancak yakınlaşabilirsiniz.

atın: http://www.antlr.org/wiki/display/ANTLR3/Tree+construction