2010-08-02 19 views
4

Je suis en train de construire une grammaire qui interprète le texte entré par l'utilisateur, le style moteur de recherche. Il prendra en charge les opérateurs booléens AND, OR, NOT et ANDNOT. J'ai à peu près tout fonctionne, mais je veux ajouter une règle que deux mots-clés adjacents en dehors d'une chaîne entre guillemets sont traités implicitement comme dans une clause AND. Par exemple:ANTLR - Implicite ET Tokens dans l'arbre

fromage et craquelins = fromage et craquelins

(haut et bas) ou (gauche et droite) = (haut et bas) OU (gauche et droite)

chien chat « porc bedaine »= chat et de chien et « porc bedaine »

Je vais avoir du mal avec le dernier, et j'espère que quelqu'un peut me diriger dans la bonne direction. Voici mon fichier * .g jusqu'à présent, et s'il vous plaît être gentil, mon expérience ANTLR couvre moins d'une journée de travail:

grammar SearchEngine; 

options { language = CSharp2; output = AST; } 

@lexer::namespace { Demo.SearchEngine } 
@parser::namespace { Demo.SearchEngine } 

LPARENTHESIS : '('; 
RPARENTHESIS : ')'; 

AND : ('A'|'a')('N'|'n')('D'|'d'); 
OR  : ('O'|'o')('R'|'r'); 
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t'); 
NOT : ('N'|'n')('O'|'o')('T'|'t'); 

fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9'); 
fragment QUOTE  : ('"'); 
fragment SPACE  : (' '|'\n'|'\r'|'\t'|'\u000C'); 

WS  : (SPACE) { $channel=HIDDEN; }; 
PHRASE : (QUOTE)(CHARACTER)+((SPACE)+(CHARACTER)+)+(QUOTE); 
WORD : (CHARACTER)+; 

startExpression : andExpression; 
andExpression : andnotExpression (AND^ andnotExpression)*; 
andnotExpression : orExpression (ANDNOT^ orExpression)*; 
orExpression  : notExpression (OR^ notExpression)*; 
notExpression : (NOT^)? atomicExpression; 
atomicExpression : PHRASE | WORD | LPARENTHESIS! andExpression RPARENTHESIS!; 

Répondre

6

Depuis votre ET-règle a l'option ET-mot-clé, vous devez créer un ET- imaginaire jeton et utilisez une règle de réécriture pour "injecter" ce jeton dans votre arbre. Dans ce cas, vous ne pouvez pas utiliser l'opérateur racine ^ d'ANTLR. Vous devrez utiliser l'opérateur de réécriture ->.

Votre andExpression devrait ressembler à:

andExpression 
    : (andnotExpression  -> andnotExpression) 
    (AND? a=andnotExpression -> ^(AndNode $andExpression $a))* 
    ; 

Une description détaillée de ce (peut-être cryptique) la notation est donnée au chapitre 7, section Règles Réécrire dans Les paragraphes, la page 173-174 de The Definitive ANTLR Reference par Terence Parr.

J'ai couru un test rapide pour voir si la grammaire produit le bon AST avec la nouvelle règle andExpression. Après analyse de la chaîne cat dog "potbelly and pig" and FOO, l'analyseur généré a produit l'AST suivante:

alt text http://img580.imageshack.us/img580/7370/andtree.png

Notez que le AndNode et Root sont imaginary tokens.

Si vous voulez savoir comment créer l'image AST ci-dessus, voir ce fil: Visualizing an AST created with ANTLR (in a .Net environment)

EDIT

Lors de l'analyse à la fois one two three et (one two) three, l'AST suivant est créé:

alt text http://img203.imageshack.us/img203/2558/69551879.png

Et lors de l'analyse (one two) OR three, l'AST suivant est créé:

alt text http://img340.imageshack.us/img340/8779/73390353.png

qui semble être la bonne façon dans tous les cas.

+0

Merci! Cela a fait l'affaire. Ma préoccupation de suivi (maintenant supprimée, et à quoi votre montage était destiné) était due à un bug dans le code C#. – user409108

+0

@highbeammeup, heureux d'entendre cela. Et vous êtes bienvenue! –

+0

@BartKiers J'ai de la difficulté à comprendre votre règle de réécriture, même si j'ai la référence ici. Pourriez-vous expliquer pourquoi la partie (..) (..) est nécessaire et ce que fait l'opérateur du dollar? –