2013-05-11 22 views
9

ANTLRv4'teki herhangi bir metin nasıl eşleştirilir? Dilbilgisi yazımı sırasında bilinmeyen metin demek istedim?ANTLR ile keyfi metin (hem sembol hem de boşluk) eşleştirme?

grammar Anytext; 

line : 
    comment; 

comment : '#' anytext; 

anytext: ANY*; 

WS : [ \t\r\n]+; 

ANY : .; 

Ve kod aşağıda sunulmuştur: My dilbilgisi olan

aşağıdaki

String line = "# This_is_a_comment"; 

    ANTLRInputStream input = new ANTLRInputStream(line); 

    AnytextLexer lexer = new AnytextLexer(input); 

    CommonTokenStream tokens = new CommonTokenStream(lexer); 

    AnytextParser parser = new AnytextParser(tokens); 

    ParseTree tree = parser.comment(); 

    System.out.println(tree.toStringTree(parser)); // print LISP-style tree 

Çıktı aşağıdaki gibidir:

line 1:1 extraneous input ' ' expecting {<EOF>, ANY} 
(comment # (anytext T h i s _ i s _ a _ c o m m e n t)) 

Şunu değiştirirsem ANY kural

ANY : [ \t\r\n.]; 

herhangi bir sembolü tanımayı durdurur.

UPDATE1

Sonunda sonu hat karaktere sahiptir.

GÜNCELLEME 2

Yani, bundan lexer birden sınıfları izin veremez çünkü lexer ile herhangi bir metin maç için imkansız olduğunu, anladım. Herhangi bir sembol için lexer kuralını tanımlarsam, diğer tüm kuralları gizler veya çalışmaz.

Ancak soru devam ediyor.

Tüm semboller ayrıştırıcı düzeyinde nasıl eşleştirilir?

Masa biçiminde verilerim olduğunu varsayalım ve bazı alanları işlemek ve başkalarını yok saymam. Ben anytext kuralı olsaydı, 2 sütun field1 ve field2 değerlerini içeriyorsa

infoline : 
    (codepoint WS 'field1' WS field1Value) | 
    (codepoint WS 'field2' WS field2Value) | 
    (codepoint WS anytext); 

burada ayrıştırma am satırları yazmak ve aksi satırları görmezden.

Bu yaklaşım nasıl gerçekleştirilir? hat yorumlar için

cevap

1

kullanın aşağıdaki kural: hattın sonuna (unix/windows satır sonları) alır kadar

LINE_COMMENT 
    : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    ; 

O '#' ve herhangi bir sembol ile eşleşir.

Düzenleme 280Z28 göre: burada ANTLR 4 sözdiziminde tam aynı kural şudur:

LINE_COMMENT 
    : '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN) 
    ; 
+0

Yazınızı, ANTLR 4 sözdiziminde tam olarak aynı kuralı vermek üzere düzenledim. Ayrı bir notta, '' r 'dahil olmak üzere * değil * öneririm? '\ n' satırı terminatörü 'LINE_COMMENT' kuralının bir parçası olarak (karakterleri tükenene kadar değil, satır sonu dahil etmeyecek şekilde). Bunu önerdiğim birkaç neden var, ancak en büyük olanı, 'LINE_COMMENT' biçiminde, bir satırın son satırındaki bir yorumla eşleşmiyorsa açık bir satır sonlandırıcısı tarafından takip edilmemesi. –

+0

evet, ANTLR 3'teydi, düzenlemeler için teşekkürler – hoaz

+0

Neden bu kadar karmaşık? Daha basit yazmak mümkün mü? Kuralım neden çalışmıyor? –

7

Bu ayrıştırıcı hiç de (ilk belirteç görmeden ANTLR jeton içine komple girdi break up olacağını hatırlamak önemlidir en azından bu şekilde davranır). Senin lexer grameriniz aşağıdaki gibi görünüyor.Giriş için

T__0 : '#'; // implicit token created due to the use of '#' in parser rule comment 

WS : [ \t\r\n]+; 

ANY : .; 

, belirteçleri aşağıdaki gibidir:

  1. # (tip T__0)
  2. [boşluk] (tip WS)
  3. T (tip ANY)
  4. h (tip ANY)
  5. i (tip ANY)
  6. s (tip ANY)
  7. _ (tip ANY)
  8. i (tip ANY)
  9. s (tip ANY)
  10. _ (tip ANY)
  11. a (tip ANY)
  12. _ (tip ANY)
  13. c (tip ANY)
  14. o (tip ANY)
  15. m (tip ANY)
  16. m (tip ANY)
  17. e (tip ANY)
  18. n (tip ANY)
  19. t (tip ANY)

Geçerli dilbilgisi WS belirteç comment kuralda izin verilmediğinden ayrıştırmak başarısız olur. Eğer kullanılırsa bu giriş ayrıştırmak olurdu (ancak dilbilgisi genişletmek olarak sorunlarla olabilir) bu:

// remember that '#' is its own token 
anytext: (ANY | WS | '#')*; 

Ne yapabilirdi boyunca # karakterini tüketir bir lexer kuralı, olmak comment değiştirmektir (aşağıdaki durumda, satırın sonuna kadar):

grammar Anytext; 

line : COMMENT; 

COMMENT : '#' ~[\r\n]*; 

WS : [ \t\r\n]+; 

ANY : .; 
+0

Ben anlamıyorum, neden [boşluk] (WS yazın)' yazdınız. Benim bakış açımdan da 'ANY'? Neden olmasın? –

+2

@SuzanCioc ANTLR hiçbir zaman bir simge için birden fazla türde atar. Uzay karakteri, "WS" ve "ANY" kurallarıyla eşleşir. Belirsizliği gidermek için, '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' ifadesi '' WS' tipi atanır. Belirsizlik giderilir ve çözümleyicinin belirteci görmeden önce atanmış olan belirteç türü, çözümleyicinin hiçbir zaman "HERHANGİ" türünde boşluk karakteri belirtecini görmez. –

+0

Peki ya ağaçlar? Lexer'da da yasaklanmışlar mı? Ya ben WS yazarsak: [\ t \ r \ n]; HERHANGİ: WS | .; '? Alan hem "ANY" ve "WS" ile işaretlenecek mi? –

İlgili konular