How can I get current line that flex/lex is lexing at the moment to use it in yyerror?

47 views Asked by At

I'm working on the simple aql parser with flex+bison as a toolkit. Right now, I'm trying to provide helpful feedback when a syntax error occurs. I want to show user somethink like this:

Syntax error:
<line_index>: INSERT { name: "John Doe", 1123: 2, is_working: true } IN users
                                         ^^^^

I already got information where syntax error occurred (line and column), but I really cant come up with getting error line. I tried to store global line buffer current_line and write content of yytext in YY_USER_ACTION macro. This way:


  #define YY_USER_ACTION \
      strcpy(current_line+cl_length, yytext); \
      for(int i = 0; yytext[i] != '\0'; i++) { \
          if(yytext[i] == '\n') { \
              memset(current_line, 0, cl_length);
              cl_length = 0;
          } else {
              cl_length++;
          }
      }
}

But I got duplicated characters at the start of lines because of usage start conditions for lexing python-like indent scopes.

Is there different way to do it with flex macro or something?

2

There are 2 answers

0
mevets On

Lex is not line oriented, so does not provide any explicit help with notions like line number. The regex operators ^,$ muddy the distinction, but you can readily handle line numbers in your scanner with a rule like:

\n { my_lineno++; }

which makes it easy for something like yywrap() to transparently funnel multiple files to the lex scanner:

extern char *files[];
extern int  nfiles;
extern int  my_lineno;
int yywrap() {
   static int curfile = 0
   static FILE *lastfile = NULL;
   FILE *fp = NULL;
   if (lastfile) {
       fclose(lastfile);
   }
   while (curfile < nfiles && fp == NULL) {
       fp = fopen(files[curfile++], "r");
   }
   yyin = lastfile = fp;
   my_lineno = 0; 
   return fp == NULL;
}

There may be other methods with flex, which substantially augments lex.

0
David Jones On

Add the following to your flex file.

%option yylineno

This option directs flex to generate a scanner that maintains the number of the current line read from its input in the global variable yylineno.

This is an undocumented lex variable and thus is also enabled when %option lex-compat is specified.

NB It is up to the user to save and restore yylineno if you are handling include files.