actions yacc

Avec chaque règle de grammaire, vous pouvez spécifier des actions à effectuer chaque fois que l'analyseur syntaxique reconnaît la règle dans le flux d'entrée. Une action est une instruction en langage C qui effectue des entrées et des sorties, appelle des sous-programmes et modifie des vecteurs et des variables externes.

Les actions renvoient des valeurs et obtiennent les valeurs renvoyées par les actions précédentes. L'analyseur lexical peut également renvoyer des valeurs pour les jetons.

Spécifiez une action dans le fichier de grammaire avec une ou plusieurs instructions incluses dans{}(accolades). Les exemples suivants sont des règles grammaticales avec des actions:
A  :  '('B')'
   {
     hello(1, "abc" );
   }
ET
XXX  :  YYY  ZZZ
     {
     printf("a message\n");
     flag = 25;
     }

Transmission de valeurs entre des actions

Pour obtenir les valeurs générées par d'autres actions, une action peut utiliser les mots clés de paramètre yacc qui commencent par le signe dollar ($1,$2, ...). Ces mots clés font référence aux valeurs renvoyées par les composants du côté droit d'une règle, en lisant de gauche à droite. Par exemple, si la règle est:
A  :  B  C  D  ;

alors$1a la valeur renvoyée par la règle qui a reconnu B,$2a la valeur renvoyée par la règle qui a reconnu C, et$3la valeur renvoyée par la règle qui a reconnu D.

Pour renvoyer une valeur, l'action définit la pseudo-variable$$à une valeur. Par exemple, l'action suivante renvoie la valeur suivante:1:
{ $$ = 1;}
Par défaut, la valeur d'une règle est la valeur du premier élément qu'elle contient ($1). Par conséquent, vous n'avez pas besoin de fournir une action pour les règles qui ont le format suivant:
A : B ;

Les mots clés de paramètre yacc supplémentaires suivants commencent par un$(symbole du dollar) permettent la vérification du type:

  • $<Balise>$
  • $<Balise>Nombre

$<Balise>Le nombre impose à la référence le type du membre de l'union référencé par<Balise>. Cela ajoute .tag à la référence afin d'accéder au membre de l'union identifié par Tag . Cette construction est équivalente à la spécification$$.Balise ou$1.Balise. Vous pouvez utiliser cette construction lorsque vous utilisez des actions au milieu de règles dans lesquelles le type de retour ne peut pas être spécifié via un%Déclaration type . Si une%type a été déclaré pour un nom non terminal, n'utilisez pas<Balise>; la référence d'union sera effectuée automatiquement.

Placer les actions au milieu des règles

Pour obtenir le contrôle du processus d'analyse syntaxique avant la fin d'une règle, écrivez une action au milieu d'une règle. Si cette règle renvoie une valeur via$, les actions qui suivent cette règle peuvent utiliser cette valeur. Cette règle peut également utiliser les valeurs renvoyées par les actions qui la précèdent. Par conséquent, les ensembles de règles suivantsxà1etyà la valeur renvoyée parC. La valeur de la règleAest la valeur renvoyée parB, en suivant la règle par défaut.
A  :  B
        {
           $$ =1;
        }
        C
   {
        x = $2;
        y = $3;
   }
   ;
En interne, la commande yacc crée un nouveau nom de symbole non terminal pour l'action qui se produit au milieu. Elle crée également une nouvelle règle correspondant à ce nom à la chaîne vide. Par conséquent, la commande yacc traite le programme précédent comme s'il avait été écrit sous la forme suivante:
$ACT  :  /* empty */
      {
         $$ = 1;
      }
      ;
A     :  B  $ACT  C
      {
         x = $2;
         y = $3;
      }
      ;

$ACTest une action vide.