Search code examples
cbison

I want to implement multiple analysis statements in bison, but each time it will succeed only when it is executed for the first time


This is my flex code:

%{
#include "parser.tab.h"
%}
%%
"save"                  { return SAVE; }
"depth"                { return DEPTH; }
"exclude"              { return EXCLUDE; }
[0-9]+                  { yylval.number = atoi(yytext); return NUMBER; }
"["                     { return LB; }
"]"                     { return RB; }
"="                     { return EQ; }
","                     { return COMMA; }
[a-zA-Z0-9_*?]+         { yylval.str = strdup(yytext); return STRING; }
[ \t\n]                 { /* ignore whitespace */ }
.                       { /* ignore unknown characters */ }
%%
int yywrap()
{
    return 1;
}

This is my bison code:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parser.tab.h"
void yyerror(char *s);
%}
%union {
    char *str;
    int number;
}
%token SAVE DEPTH EXCLUDE
%token LB RB EQ COMMA NUMBER STRING
%%
command:
    | SAVE DEPTH EQ NUMBER EXCLUDE EQ NUMBER { printf("Command parsed successfully.\n"); }
    | error { printf("Error: Invalid command.\n"); }
    ;
%%
int main()
{
    yyparse();
    yyrestart();
    return 0;
}
void yyerror(char *s)
{
    printf("ERROR:%s\n",s);
}

This is the result when I ./parser :

save depth=1 exclude=1
Command parsed successfully.
save
ERROR:syntax error
Error: Invalid command.
Error: Invalid command.
save depth=1 exclude=1
Error: Invalid command.
Error: Invalid command.
Error: Invalid command.
Error: Invalid command.
Error: Invalid command.
Error: Invalid command.
Error: Invalid command.

The first time it will succeed, the next time it will all fail.


Solution

  • You have made the standard beginners mistake of only defining the syntax of a single command, but supplied a file containing more than one command, and thus bison informs you that it does not match the syntax of a single command!

    You need to define the syntax of the whole language|file|program. I see you expect the input to be one command per-line, so this is what you have to instruct bison:

    input: command
         | command NEWLINE input
    

    Then it will process a sequence of commands, each one on a line.

    You will then need to redefine your whitespace in the lexer, as the end-of-line now has significance.