2011-07-20 2 views
3

Je suis coincé avec cela depuis un moment maintenant. Je veux analyser quelque chose d'aussi simple que:Grammaire simple pour Lemon LALR Parser

aime: mot1 mot2 .. wordN DÉTESTE: mot1 mot2 .. wordN

J'utilise Lemon + Flex. Pour le moment ma Grammaire ressemble à ceci:

%left LIKES MOODS FROM HATES INFO. 

%syntax_error { 
    std::cout << "Syntax error!" << std::endl; 
} 

final ::= likes_stmt. 
final ::= hates_stmt. 

likes_stmt ::= LIKES list(A). { Data *data=Data::getInstance();data->likes.push_back(A);} 
hates_stmt ::= HATES list(A). { Data *data=Data::getInstance();data->hates.push_back(A);} 

list ::= likes_stmt VALUE(A). { Data *data=Data::getInstance();data->likes.push_back(A);} 
list ::= hates_stmt VALUE(A). { Data *data=Data::getInstance();data->hates.push_back(A); } 

list(A) ::= VALUE(B).   {A=B;} 

Mais cela ne fonctionne que pour les 2 premiers mots. Clairement je fais quelque chose de mal, probablement dans la définition récursive? Toute tête haute est appréciée :)

Répondre

2

@crozzfire, Ira fourni la réponse correcte à votre question, veuillez voter pour. Permettez-moi de répondre à la question avec votre besoin supplémentaire de séparer les valeurs analysées en deux listes. Ne créez pas de règles différentes pour l'analyse de ces listes car la grammaire de la liste est la même dans les deux cas. Ce dont vous avez besoin est un drapeau pour indiquer si LIKES ou HATES a été trouvé en tête de liste. Le 4ème paramètre de la fonction Parse de Lemon convient le mieux à ce besoin. Voir la section "L'interface de l'analyseur" de Lemon documentation.

Ci-dessous est mise à jour la grammaire d'Ira qui définit et vérifie une telle variable de drapeau. Prenez note que les règles set_likes_state et set_hites_state doivent être placées juste avant le jeton LIKES et HATES pour que l'action associée soit exécutée lorsque les jetons sont réduits.

%extra_argument {unsigned* state} 

    final ::= likes_stmt. 
    final ::= hates_stmt. 

    likes_stmt ::= set_likes_state LIKES list(A). 
    hates_stmt ::= set_hites_state HATES list(A). 

    list ::= list VALUE(A). { if (*state == 0) {/*add A to list1*/} else {/*add A to list2*/}; } 
    list ::= VALUE(A).  { if (*state == 0) {/*add A to list1*/} else {/*add A to list2*/}; } 

    set_likes_state ::= .  { *state = 0; } 
    set_hites_state ::= .  { *state = 1; } 
+0

Habituellement, la façon dont cela est fait est d'analyser d'abord, et le post-processus de l'arbre pour recueillir des informations dans diverses catégories. De cette façon, vous ne fausserez pas la grammaire avec des productions artificielles ("set_likes", etc.) dont le seul travail est de signaler aux actions "en-parsing". Dans des langages plus complexes, ces signaux ne font que créer du chagrin parce que l'encombrement de la grammaire et l'analyse de l'enchevêtrement avec le travail. Cependant, si c'est * tout * OP doit faire, alors cette réponse est bien. (Merci pour l'upvote!) –

2

Il me semble que votre likes_stmt est défini en termes de liste, et la liste est définie en termes de likes. Je suis surpris que cela fonctionne pour tous les mots du tout. Il se peut que je ne comprenne pas la syntaxe de LEMON (je n'obtiens pas le bit de la liste (A)), mais les grammaires BNF ont tendance à être assez similaires.

J'attends votre grammaire ressemble davantage:

final = likes_stmt ; 

likes_stmt = LIKES list ; 
likes_stmt = HATES list ; 


    list = value ; 
    list = list value ; 

Bien sûr, cela ne reconnaîtrait une phrase Goûts, ou une phrase DÉTESTE, mais pas les deux en même temps ou que pour que sous-entendus par ligne 2 de votre question.

+0

Merci pour votre réponse. Mais j'ai peur d'avoir déjà essayé ça. Fondamentalement, ce que j'essaye de faire est de pousser les cordes à leurs places respectives (LIKES ou HATES). À l'avenir, j'aurai des jetons plus réservés tels que INFO, MOODS, etc. C'est très similaire à la syntaxe de recherche avancée de Google. – crozzfire

+0

Les générateurs d'analyseur sont très faciles à utiliser et assez robustes pour l'analyse syntaxique. Je vous suggère de vous débarrasser de toutes les actions d'action sémantique supplémentaires dans votre grammaire, par exemple de les réduire à peu près à ce que j'ai écrit, et de l'essayer à nouveau. Si cela fonctionne, commencez à ajouter vos actions sémantiques. –

Questions connexes