SORU
16 HAZİRAN 2010, ÇARŞAMBA


A 'semantik yüklem' ANTLR nedir?

Bir şeydirsemantik yüklemiçinde ANTLR?

CEVAP
16 HAZİRAN 2010, ÇARŞAMBA


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

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • jbignacio

    jbignacio

    13 Mart 2006
  • Lamarr Wilson

    Lamarr Wilso

    27 Aralık 2008
  • TWiT Netcast Network

    TWiT Netcast

    27 EKİM 2005