A 'semantik yüklem' ANTLR nedir?
Bir şeydirsemantik yüklemiçinde ANTLR?
CEVAP
ANTLR 4
İçin ANTLR 4, Bu ödeme koşullarınayığıntaşmaQ&A:
ANTLR 3
Birsemantik yüklemdilbilgisi üzerine (semantik) ekstra kurallarını uygulamak için bir yoldur eylemler düz kodunu kullanarak.
Semantik doğrulamaları 3 tipi vardır:
- doğrulanıyorsemantik koşullarına;
- geçitlisemantik koşullarına;
- disambiguatinganlam ifade eder.
Örnek dilbilgisi
Hadi metin bloğu yalnızca sayı ile ayrılmış oluşan söyleyin
virgül, herhangi bir beyaz boşluk görmezden. Bu giriş yapma ayrıştırmak istiyorum
sayıları 3 basamaklı en emin "" (en fazla 999). uzun Aşağıdaki
dilbilgisi (Numbers.g
) böyle bir şey yapsın ki:
grammar Numbers;
// entry point of this parser: it parses an input string consisting of at least
// one number, optionally followed by zero or more comma's and numbers
parse
: number (',' number)* EOF
;
// matches a number that is between 1 and 3 digits long
number
: Digit Digit Digit
| Digit Digit
| Digit
;
// matches a single digit
Digit
: '0'..'9'
;
// ignore spaces
WhiteSpace
: (' ' | '\t' | '\r' | '\n') {skip();}
;
Test
Dilbilgisi aşağıdaki sınıf ile test edilebilir:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7 , 89");
NumbersLexer lexer = new NumbersLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
NumbersParser parser = new NumbersParser(tokens);
parser.parse();
}
}
Lexer ve ayrıştırıcı .java
tüm dosyalar derleme ve üreterek Test
Main
sınıf koşu:
java -cp antlr-3.2.jar org.antlr.Tool Numbers.g javac -cp antlr-3.2.jar *.java java -cp .:antlr-3.2.jar Main
Bunu yaparken, hiçbir şey, hiçbir şey gösterir konsola yazdırılır yanlış gitti. Değiştirmeyi deneyin:
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7 , 89");
içine:
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7777 , 89");
ve Testi tekrar yapın: bir hata dizesini hemen sonra konsolu 777
. görünen göreceksiniz
Anlam İfade Eder
Bu anlamsal doğrulamaları için bize getiriyor. Hadi ayrıştırmak için istediğini söyle 1 ile 10 arasındaki rakamları basamak uzunluğunda. Bir kural gibi:
number
: Digit Digit Digit Digit Digit Digit Digit Digit Digit Digit
| Digit Digit Digit Digit Digit Digit Digit Digit Digit
/* ... */
| Digit Digit Digit
| Digit Digit
| Digit
;
hantal olacak. Semantik koşullarına bu tür bir kural basitleştirmek yardımcı olabilir.
1. Semantik Koşullarına Doğrulanıyor
Birsemantik yüklem doğrulanıyorbir şey kod bloğu sonunda bir soru işareti daha:
RULE { /* a boolean expression in here */ }?
Bir kullanarak yukarıdaki sorunu çözmek içindoğrulanıyor
semantik yüklem, dilbilgisi number
kural değişikliği:
number
@init { int N = 0; }
: (Digit { N ; } ) { N <= 10 }?
;
Hangi parçaları { int N = 0; }
{ N ; }
düz Java, açıklamaları
ilk çözümleyici "" number
kural. girdiğinde başlatıldı Gerçek
yüklem: çözümleyici bir durum neden olur { N <= 10 }?
,
FailedPredicateException
bir numara her zaman 10'dan fazla basamak uzunluğundadır.
33**: aşağıdaki kullanarak Test edin
// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890");
aşağıda bir istisna istemiyorum yok iken: istisna, üretir
// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");
2. Semantik Koşullarına Kapılı
Birkapı semantik yüklembir benzersemantik yüklem doğrulanıyor,
tekgeçitlisürüm FailedPredicateException
bir yerine bir sözdizimi hatası üretir.
Bir sözdizimikapı semantik yüklem:
{ /* a boolean expression in here */ }?=> RULE
Bunun yerine yukarıdaki kullanarak sorunu çözmek içingeçitlinumaraları 10 haneli maç koşullarına yazarsınız:
number
@init { int N = 1; }
: ( { N <= 10 }?=> Digit { N ; } )
;
Yine de Test:
// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890");
ve:
// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");
ve bir hata atar son göreceksiniz.
3. Semantik Koşullarına Disambiguating
Yüklem son türüsemantik yüklem disambiguatingbiraz doğrulanıyor bir yüklem ({boolean-expression}?
) gibi görünüyor, ama daha kapı semantik bir yüklem (istisna boolean ifadesi 42 ** olur, atılır) gibi davranır., Bir kural bir özelliğini kontrol etmek için bir kural başlangıcında kullanın ve çözümleyici dedi kural veya Maç sağlayabilirsiniz.
Hadi örnek dilbilgisi 0..999 aralığında numaraları maç olacak Number
belirteçleri (ayrıştırıcı bir kural yerine lexer kuralı) oluşturur söylüyorlar. Şimdi çözümleyici, düşük ve yüksek sayılar (düşük: 0..500, yüksek: 501..999) arasında bir ayrım yapmak istiyorum. Bu işi bir şekilde kullanıyor olabilirsemantik yüklem disambiguatingakış (input.LT(1)
) ise, düşük veya yüksek olup olmadığını kontrol etmek için token sonraki inceleyin.
Demo:
grammar Numbers;
parse
: atom (',' atom)* EOF
;
atom
: low {System.out.println("low = " $low.text);}
| high {System.out.println("high = " $high.text);}
;
low
: {Integer.valueOf(input.LT(1).getText()) <= 500}? Number
;
high
: Number
;
Number
: Digit Digit Digit
| Digit Digit
| Digit
;
fragment Digit
: '0'..'9'
;
WhiteSpace
: (' ' | '\t' | '\r' | '\n') {skip();}
;
Şimdi dize ayrıştırma "123, 999, 456, 700, 89, 0"
aşağıdaki çıktıyı görmek istiyorum:
low = 123
high = 999
low = 456
high = 700
low = 89
low = 0
'en uzun olası dünya çapında tele...
Makul bir uzunlukta kişi "Adı&quo...
Toplama ve Java Listesinde arasındaki ...
CamelCase (hiçbir sözcük ayırıcı) tümü...
Nasıl bir NSDictionary içine saklayabi...