2017-04-14 6 views
2

Je suis nouveau à fléchir et le bison alors ours avec moi. J'essaye d'employer yylloc dans yyerror pour imprimer où l'erreur se produit avec le nom de fichier. Je sais que cela m'oblige à redéfinir YYLTPYE pour inclure un nom de fichier char * que je peux utiliser pour garder une trace du nom de fichier. Selon le livre Flex et Bison je, il recommande que j'utilise la macro YY_USER_ACTION pour initialiser le YYLTYPE dans le fichier .L, donc je compris ce qui suit dans ce,Comment résoudre une erreur yylloc non déclarée?

#define YY_USER_ACTION yylloc.filename = filename; yylloc.hel = 0; \ 
     yylloc.first_line = yylloc.last_line = yylineno;   \ 
     yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \ 
     yycolumn += yyleng; 

mais lorsque je tente de compiler le projet, j'ai l'erreur que Yylloc est non déclaré.

J'ai essayé la solution proposée par Chris Dodd dans ce question, mais cela ne m'a pas aidé à résoudre le problème. Toute aide pour résoudre cette erreur est très appréciée.

Voici le code complet en .L:

%option noyywrap nodefault yylineno case-insensitive 
%{ 
    #include "need.h" 
    #include "numbers.tab.h" 

    int yycolumn = 1; 

    #define YY_USER_ACTION yylloc.filename = filename; yylloc.hel = 0; \ 
     yylloc.first_line = yylloc.last_line = yylineno;   \ 
     yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \ 
     yycolumn += yyleng; 

%} 

Integers [-]?(0|[1-9][0-9]*) 
Float  [.][0-9]+ 
Exp   [eE][-]?(0|[1-9][0-9]*) 
Octal  [-]?(00|0[1-7][0-7]*) 
Hexa  [-]?(0[xX][0-9A-F]+) 
tomsNotNumbers [^ \t\n\v\f\r]+ 

%% 

{Integers}{Float}?{Exp}? { 
           printf("%s is a number.\n", yytext); 
           possibleNumbers++; // increment by 1 as an input was given -M 
           actualNumbers++; // increment by 1 as an input did match our pattern -M 
          } 

{Octal} { 
      printf("%s is a number.\n", yytext); 
      possibleNumbers++; // increment by 1 as an input was given -M 
      actualNumbers++; // increment by 1 as an input did match our pattern -M 
     } 

{Hexa} { 
      printf("%s is a number.\n", yytext); 
      possibleNumbers++; // increment by 1 as an input was given -M 
      actualNumbers++; // increment by 1 as an input did match our pattern -M 
     } 

{tomsNotNumbers} { 
        printf("%s is not a number.\n", yytext); 
        yyerror(warning, "This isn't a number."); 
        possibleNumbers++; // increment by 1 as an input was given -M 
        failedNumbers++; // increment by 1 as the input has failed to match our patterns -M 
       } 

[\n] /*Do nothing for newline*/ 

. /*Do nothing for anything else*/ 

%% 

.y est juste vide pour l'instant, a seulement une pour inclure need.h et un pour .tab.h

Le need.h :

#include <stdlib.h> 
#include <stdarg.h> 
#include <string.h> 

int possibleNumbers = 0; 
int actualNumbers = 0; 
int failedNumbers = 0; 

typedef struct YYLTYPE 
{ 
    int first_line; 
    int first_column; 
    int last_line; 
    int last_column; 
    char *filename; /* use to keep track of which file we're currently in */ 
    int hel; /* no errors = 0, warning = 1, error = 2, fatal = 3 */ 
} YYLTYPE; 

char *name; /*using for test purposes*/ 

# define YYLTYPE_IS_DECLARED 1 

# define YYLLOC_DEFAULT(Current, Rhs, N)             \ 
    do                      \ 
     if (N)                    \ 
     {                     \ 
      (Current).first_line = YYRHSLOC (Rhs, 1).first_line;       \ 
      (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \ 
      (Current).last_line = YYRHSLOC (Rhs, N).last_line;        \ 
      (Current).last_column = YYRHSLOC (Rhs, N).last_column;       \ 
      (Current).filename = YYRHSLOC (Rhs, 1).filename;        \ 
      (Current).hel = YYRHSLOC (Rhs, 1).hel;          \ 
     }                     \ 
     else                    \ 
     { /* empty RHS */                 \ 
      (Current).first_line = (Current).last_line = YYRHSLOC (Rhs, 0).last_line;  \ 
      (Current).first_column = (Current).last_column = YYRHSLOC (Rhs, 0).last_column; \ 
      (Current).filename = NULL;              \ 
      (Current).hel = 0;                \ 
     }                     \ 
    while (0) 

typedef enum errorSeverity 
{ 
    warning = 1, error, fatal 
} errorLevel; 

void yyerror(errorLevel errlvl, char *s, ...) 
{ 
    va_list ap; 
    va_start(ap, s); 
    char *errLvls[3] = {"Warning", "Error", "Fatal"}; 

    fprintf(stderr, "%s: %s: , %n", name, errLvls[errlvl - 1], yylloc.first_line); 
    vfprintf(stderr, s, ap); 
    fprintf(stderr, "\n"); 
} 

main(int argc, char **argv) 
{ 
    printf("argv[0] = %s, argv[1] = %s.\n", argv[0], argv[1]); 
    if(argc > 1) 
    { 
     if((yyin = fopen(argv[1], "r")) == NULL) 
     { 
      perror(argv[1]); 
      exit(1); 
     } 
     name = argv[1]; 
    } else 
     name = "(stdin)"; 

    printf("Filename1: %s", name); 
    yylex(); 
    printf("Filename2: %s", name); 
    // print out the report. -M 
    printf("Out of %d possible numbers, there were %d numbers, and %d not numbers.\n", possibleNumbers, actualNumbers, failedNumbers); 
} 

Répondre

2

Depuis yylloc est normalement défini dans l'analyseur généré bison, ne pas avoir un fichier d'entrée bison va être un peu gênant.

Bison définira yylloc dans l'analyseur généré, et placez une déclaration dans le fichier d'en-tête généré, si:

  1. Vous incluez la directive %locations dans le prologue de bison ou

  2. référence Vous un emplacement (@n pour certains n) dans n'importe quelle action de bison.

Il est généralement préférable d'ajouter la directive dans le cas où il n'y a pas de référence explicite à un emplacement dans une règle. Comme le dit Chris Dodd dans la question liée, il est important d'inclure la définition de YYLTYPE avant #include dans le fichier d'en-tête généré par bison. Vous pouvez également insérer la définition de la structure, ou un #include approprié, directement dans le prologue de bison dans une section %code requires. Les sections %code requires sont copiées dans l'en-tête généré, ce qui évite d'avoir à se soucier de la définition dans le fichier flex.


D'ailleurs, je pense que vous vouliez dire utiliser YY_USER_INIT-initializeyylloc. L'expansion de YY_USER_INIT est exécutée une seule fois, avant l'initialisation du scanner Flex. L'extension de YY_USER_ACTION est exécutée avant chaque action de l'analyseur (y compris les actions vides) et est susceptible d'être utilisée pour mettre à jour la structure yylloc avec le jeton en cours.

+0

Merci pour l'info, j'ai été en mesure de résoudre l'erreur en ajoutant% emplacements et en définissant la définition de YYLTYPE dans un code% nécessite un bloc dans le fichier. Il dit maintenant une référence indéfinie à 'yylloc' à plusieurs reprises, puis une erreur collect @: error: ld a retourné 1 status de sortie.Est-ce parce que mon analyseur n'a rien encore dedans, ou a-t-il manqué quelque chose? –

+0

Avez-vous lié l'analyseur généré par bison dans l'exécutable? – rici

+0

voici mon makefile: chiffres: numbers.l numbers.y \t bison -d numbers.y \t numbers.l flex \t gcc lex.yy.c numbers.tab.h -lfl –