Frage

Was ist ein semantische Prädikat in ANTLR?

War es hilfreich?

Lösung

ANTLR 4

Für Prädikate in ANTLR 4, Check-out diese Stapel Überlauf Q & A:


ANTLR 3

semantisches Prädikat ist ein Weg, um zusätzliche zu erzwingen (semantische) Regeln auf Grammatik mit Klar Code Aktionen.

Es gibt 3 Arten von semantischen Prädikaten:

  • Validieren semantische Prädikate;
  • gated semantische Prädikate;
  • Entscheider semantische Prädikate.

Beispiel Grammatik

Lassen Sie uns sagen haben Sie einen Textblock, der nur aus Zahlen, getrennt durch Komma ist, keine weißen Flecken zu ignorieren. Sie möchten uns an dieser Eingabeprozess analysieren Sie sicher, dass die Zahlen sind höchstens 3 Ziffern „long“ (höchstens 999). Folgende Grammatik (Numbers.g) würde so etwas tun:

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();}
  ;

Testing

Die Grammatik kann mit der folgenden Klasse getestet werden:

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();
    }
}

Test durch den Lexer und Parser zu erzeugen, Kompilieren alle .java Dateien und die Main Klasse ausgeführt wird:

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

Dabei ist nichts auf die Konsole ausgegeben, die, dass nichts anzeigt ging schief. Versuchen Sie,:

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7   , 89");

in:

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7777   , 89");

und machen Sie den Test erneut. Sie werden sehen, ein Fehler auf der Konsole direkt nach der Zeichenfolge 777 erscheinen


Semantic Prädikate

Dies bringt uns zu den semantischen Prädikaten. Angenommen, Sie möchten analysieren Zahlen zwischen 1 und 10 Stellen lang. Eine Regel wie:

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
  ;

wäre mühsam geworden. Semantic Prädikate simplify diese Art der Regel helfen kann.


1. Validieren Semantic Prädikate

A Validieren semantische Prädikat ist nichts mehr als ein Code-Block durch ein Fragezeichen:

RULE { /* a boolean expression in here */ }?

Um das Problem zu lösen, oben mit einem Validieren semantisches Prädikat, das number Regel in der Grammatik ändern:

number
@init { int N = 0; }
  :  (Digit { N++; } )+ { N <= 10 }?
  ;

Die Teile { int N = 0; } und { N++; } sind reine Java-Anweisungen, von denen der erste initialisiert wird, wenn der Parser „tritt“ die number Regel. die eigentliche Prädikat: { N <= 10 }?, die der Parser verursacht eine werfen FailedPredicateException immer dann, wenn eine Zahl von mehr als 10 Ziffern lang sein.

Test durch die folgende ANTLRStringStream mit:

// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890"); 

, die keine Ausnahme erzeugt, während die folgenden tut thow eine Ausnahme:

// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");

2. Gated Semantic Prädikate

A gated semantische Prädikat ist ähnlich ein Validieren semantische Prädikat , nur die gated Version erzeugt einen Syntaxfehler statt eines FailedPredicateException.

Die Syntax eines gated semantisches Prädikat ist:

{ /* a boolean expression in here */ }?=> RULE

Um stattdessen löst das oben genannte Problem mit gated Prädikaten Zahlen zu 10 Stellen zusammenpassen lange würden Sie schreiben:

number
@init { int N = 1; }
  :  ( { N <= 10 }?=> Digit { N++; } )+
  ;

Test wieder mit beiden:

// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890"); 

und

// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");

und Sie werden die letzte sehen werden einen Fehler aus.


3. Disambiguieren Semantic Prädikate

Die letzte Art von Prädikat ist ein Entscheider semantisches Prädikat , die ein bisschen wie ein Validieren Prädikat aussieht ({boolean-expression}?), sondern wirken eher wie eine Gated semantisches Prädikat (keine Ausnahme ausgelöst wird, wenn dieBooleschen Ausdruck ergibt false). Sie können es zu Beginn einer Regel verwenden, das eine Eigenschaft der Regel zu überprüfen und lassen Sie den Parser Spiel der Regel oder nicht.

Lassen Sie uns sagen, dass die Beispielgrammatik erzeugt Number Token (eine Lexer Regel statt einer Parser-Regel), die Zahlen im Bereich von 0..999 übereinstimmen. Jetzt im Parser, Sie mögen einen Unterschied zwischen Niedrig- und Höhe Zahlen machen (low: 0..500, hoch: 501..999). Dies könnte getan werden, eine mit Entscheider semantischem Prädikat , wo Sie inspizieren das Token als nächste in dem Stream (input.LT(1)) zu überprüfen, ob es entweder niedrig oder hoch ist.

Eine 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();}
  ;

Wenn Sie jetzt die Zeichenfolge "123, 999, 456, 700, 89, 0" analysieren, würden Sie die folgende Ausgabe sehen:

low  = 123
high = 999
low  = 456
high = 700
low  = 89
low  = 0

Andere Tipps

Ich habe immer den lapidaren Verweis auf ANTLR Prädikate auf wincent.com als meinen Führer verwendet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top