0
votes

I'm getting an "unexpected identifier error", at 1-9, on the line

string_op   | string_lit                { $$ = $1; }

here is my grammar

%union 
{
    int intval;
    double dubval;
    char* strval;   
    obj object;
}

%token <intval> INTEGER 
%token <dubval> DOUBLE 
%token <strval> STRING_LITERAL

%type <object> number factor value term constant string_lit string_op element

%%
number      : INTEGER               { $$.type = 0;
                                      $$.ival = $1; }
            | DOUBLE                { $$.type = 1;
                                      $$.dval = $1; }
            ;

factor      : number                { $$ = $1; }
            | '(' constant ')'      { $$ = $2; } 
            ;

value       : factor                { $$ = $1; }
            | value '^' factor      { doMath(&$$, $1, $3, '^'); }   
            ;

term        : value                 { $$ = $1; }
            | term '*' value        { doMath(&$$, $1, $3, '*'); }
            | term '/' value        { doMath(&$$, $1, $3, '/'); }
            | term '%' value        { doMath(&$$, $1, $3, '%'); }
            ;

constant    : term                  { $$ = $1; }
            | constant '+' term     { doMath(&$$, $1, $3, '+'); }
            | constant '-' term     { doMath(&$$, $1, $3, '-'); }
            ;

string_lit  : STRING LITERAL        { $$.type = 2; 
                                      $$.string = malloc(sizeof(strlen($1))+1);
                                      memcpy($$.string, $1, sizeof($1));        }
            ;

string_op   | string_lit                { $$ = $1; }
            | string_op '+' string_lit  { concat(&$$, $1, $3); }
            ;

variable    : string_op                 { $$ = $1; }
            | constant                  { $$ = $1; }
            | variable '+' string_op    { doMath(&$$, $1, $3, '+') };
            | variable '+' constant     { doMath(&$$, $1, $3, '+') };
            | variable '-' string_op    { doMath(&$$, $1, $3, '-') };
            | variable '-' constant     { doMath(&$$, $1, $3, '-') };
            | variable '*' string_op    { doMath(&$$, $1, $3, '*') };
            | variable '*' constant     { doMath(&$$, $1, $3, '*') };
            | variable '/' string_op    { doMath(&$$, $1, $3, '/') };
            | variable '/' constant     { doMath(&$$, $1, $3, '/') };
            | variable '%' string_op    { doMath(&$$, $1, $3, '%') };
            | variable '%' constant     { doMath(&$$, $1, $3, '%') };
            | variable '^' string_op    { doMath(&$$, $1, $3, '^') };
            | variable '^' constant     { doMath(&$$, $1, $3, '^') };
            | variable '>' string_op    { doMath(&$$, $1, $3, '>') };
            | variable '>' constant     { doMath(&$$, $1, $3, '>') };
            | variable '<' string_op    { doMath(&$$, $1, $3, '<') };
            | variable '<' constant     { doMath(&$$, $1, $3, '<') };
            | variable GT_EQ string_op  { doMath(&$$, $1, $3, '.') }; //>=
            | variable GT_EQ constant   { doMath(&$$, $1, $3, '.') }; 
            | variable LT_EQ string_op  { doMath(&$$, $1, $3, ',') }; //<=
            | variable LT_EQ constant   { doMath(&$$, $1, $3, ',') };
            ;
%%

Ive declared "string_op" already, in the "%type" line. I'm not really sure what to make of this.

1

1 Answers

2
votes

The error message should probably have said "Unexpected |", because what is expected after string_op is a :.

The reason bison produces that odd error message is that the bison lexer combines an identifier with a following : into a single token whose type is id_colon instead of identifier. It does that because ; is optional at the end of a rule, and the bison rule grammar would therefore be LR(2) if : were a token on its own. (Ironic, really.) So it was expecting an id_colon and it unexpectedly found an identifier.