2017-08-03 6 views
0

Ich arbeite mit Antlr4, um eine boolesche DSL zu analysieren.Antlr4 Grammatik - Probleme identifizieren Grammatik

Hier ist meine Grammatik:

grammar filter; 

filter: overall EOF; 

overall 
    : LPAREN overall RPAREN 
    | category 
    ; 

category 
    : expression # InferenceCategory 
    | category AND category # CategoryAndBlock 
    | label COLON expression # CategoryBlock 
    | LPAREN category RPAREN # NestedCategory 
    ; 

expression 
    : NOT expression   # NotExpr 
    | expression AND expression # AndExpr 
    | expression OR expression # OrExpr 
    | atom      # AtomExpr 
    | LPAREN expression RPAREN # NestedExpression 
    ; 

label 
    : ALPHANUM 
    ; 

atom 
    : ALPHANUM 
    ; 

Hier ist ein Beispiel Eingabestring zu analysieren:

(cat1: (1 oder 2) und cat2 :(4))

Diese Grammatik funktioniert gut mit dieser Eingabe; es erzeugt den folgenden Parsing-Baum, die meine Bedürfnisse passen perfekt:

enter image description here

Allerdings gibt es seltsamen Fall des DSL, wo das „cat1“ label implizit ist, wenn keine andere Kategorie angegeben ist. Das fängt das InferenceCategory-Tag ab, wobei dieser Ausdruck später in meinem Code als Kategorie behandelt wird.

Zum Beispiel mit

((1 oder 2) und cat2 :(4))

ich (wie erwartet):

enter image description here

jedoch , im folgenden Beispiel:

CAT2 :() und (1 oder 2)

I erhalten:

enter image description here

bemerkt, dass der zweite Block wird als InferenceCategory nicht identifiziert und sondern als normale Expression, unter der ersten Kategorie. Dies liegt daran, dass dort die Grammatik (4) nach cat2 analysiert: als normaler Ausdruck, und alles, was darüber liegt, wird als normaler Ausdruck geparst.

Gibt es eine Möglichkeit, das zu beheben? Ich habe versucht:

label COLON expression (AND category)* # CategoryBlock (was nicht funktioniert)

und

category AND category AND category (welche „funktioniert“, ist aber extrem Hacky und funktioniert nur in dem speziellen Fall, dass ich genau haben drei Kategorien.Jeder mehr, und es bricht wieder.)

Antwort

1

Die "alternativen Etiketten" wie NOT expression # NotExpr machen keinen Unterschied in Ihrem Syntaxbaum. Sie sind nur semantisch. Sie bewirken, dass der Codegenerierungsprozess bestimmte Signaturen erstellt, die Sie in Ihrem Besucher oder Listener überschreiben können.

Der Grund dafür ist, dass zum Beispiel anstatt nur eine Visitor Override für expression zu erhalten, Sie mehrere, eine für jedes alternative Etikett erhalten. Auf diese Weise müssen Sie expression nicht untersuchen und bestimmen, um welchen Typ es sich handelt, bevor Sie darauf reagieren.Stattdessen erhalten Sie beispielsweise eine Außerkraftsetzung für # OrExpr, und sobald Sie sich in diesem Außerkraftsetzungscode befinden, wissen Sie, dass Sie sich mit einem OR befassen, mit einem Ausdruck auf jeder Seite des OR-Tokens.

Der Syntaxbaum ist nützlich, aber ein großer Teil der Semantik wird erst beim Codieren des Listeners oder Visitors sichtbar.

+0

Hallo, ich bin mir bewusst, dass die alternativen Etiketten nur semantisch sind, bis ich mit dem Listener/Visitor arbeite. In diesem Fall bin ich nicht wirklich sicher, wie diese impliziten Kategorien auf der Parser-Ebene eindeutig identifiziert werden können, da sie funktional identisch sind. Meine aktuelle Implementierung, in der ich das Problem einfach ignoriere, funktioniert bis zu dem Fall, in dem eine dieser impliziten Kategorien rechts von meinem "label: expression" steht. In diesem Fall wird es als Ausdruck und nicht als Kategorie interpretiert wird zu einem Teilbaum der anderen Kategorie anstelle eines Geschwisters (was das Hauptproblem ist). – thevises

Verwandte Themen