2009-06-24 7 views
1

Ich bin ein totaler Lexer und Parser Neuling, also bitte etwas Geduld. Schließlich möchte ich in der Lage sein, LDAP-Stil-Abfragezeichenfolgen auszudrücken, z. '(foo = bar)', '(! foo = bar)', '(& (foo = bar) (! zip = zap))' und habe am Ende einen Baum, mit dem ich die eigentliche Datenbankabfrage erstellen konnte (oder was auch immer)ANTLR (Feld = Wert), wie drückt man das aus?

Also dachte ich, mit der einfachsten Form zu beginnen, um Ausdrücke wie (foo = bar) und (! foo = bar) zu parsen, aber ich habe schon einige Probleme zu verstehen. Ich möchte nur ausdrücken, dass die Felder durch ein '=' vom Wert getrennt sind, aber ANTLR scheint alle Zeichen auf einmal zu essen, weil der Identifizierer viel wie ein Wert aussieht. Was muss ich tun, um dies zu verhindern?

grammar FilterExpression; 

options 
{ 
    language=Java; 
    k=2; 
} 

tokens 
{ 
    NOT='!'; 
} 

term : '(' NOT? FIELD '=' VALUE ')'; 
// lexer 
FIELD : NAME; 
VALUE : CDATA; 

fragment NAME 
    : ALPHA+; 
fragment CDATA 
    : ALPHA*; 
fragment ALPHA 
    : ('a'..'z' | 'A'..'Z'); 

Antwort

0

Wenn Felder und Werte beiden Kennungen sind, in denen eine Kennung eine nicht leere Zeichenfolge aus alphabetischen Zeichen ist (Wert ermöglichen leer zu sein, wie in Ihrem Beispiel), könnten Sie so etwas wie:

term :  '(' NOT? field '=' value ')'; 

field : IDENTIFIER ; 

value : IDENTIFIER? ; 

// lexer 
IDENTIFIER : ALPHA+ ; 

fragment ALPHA 
    : ('a'..'z' | 'A'..'Z'); 

Da der Lexer ein Feld nicht von einem Wert unterscheiden kann, muss der Lexer sie gleich behandeln und den Parser verwenden, um den Unterschied basierend auf dem Kontext zu ermitteln.

2

Okay, Sie sind hier auf dem richtigen Weg. Nur ein paar Dinge, die Sie ändern müssen. Sie müssen die Feldname und Feld Wert im Parser lieber als im Lexer, da der Lexer hat keine Möglichkeit, den Unterschied zwischen diesen beiden zu sagen. Mehrere Lexer-Ausdrücke, die dasselbe Fragment verwenden, machen es sehr schwierig (unmöglich!), Dass der Lexer bestimmt, welche davon gewünscht wird. Die Bestimmung dieser beiden (Name und Wert) in den Parser zu verschieben, macht es sehr einfach. Um den Wert optional zu machen, machen Sie einfach diesen Parserbegriff optional (mit dem '?' Dahinter). Siehe unten für den Parse-Baum, der mit der modifizierten Grammatik erzeugt wurde (hoffentlich ist es das, wonach du gesucht hast). Ich habe auch die modifizierte Grammatik am Ende meiner Antwort für Sie eingefügt.
alt text http://img268.imageshack.us/img268/7374/graphw.png

grammar FilterExpression; 

options 
{ 
    language=Java; 
    k=2; 
} 

tokens 
{ 
    NOT='!'; 
} 

term :  '(' NOT? field '=' value? ')'; 
// lexer 
field :  ID; 
value :  ID; 

ID : ALPHA+ 
    ; 

fragment ALPHA 
    : ('a'..'z' | 'A'..'Z'); 
Verwandte Themen