2
votes

I recently started learning bison and I already hit a wall. The manual sections are a little bit ambiguous, so I guess an error was to be expected. The code below is the first tutorial from the official manual - The Reverse Polish Notation Calculator, saved in a single file - rpcalc.y.

/* Reverse polish notation calculator */

%{
    #include <stdio.h>
    #include <math.h>
    #include <ctype.h>
    int yylex (void);
    void yyerror (char const *);
%}

%define api.value.type {double}
%token NUM

%% /* Grammar rules and actions follow. */

input:
    %empty
|   input line
;

line:
    '\n'
|   exp '\n'    {printf ("%.10g\n", $1);}
;

exp:
    NUM         {$$ = $1;          }
|   exp exp '+' {$$ = $1 + $2;      }
|   exp exp '-' {$$ = $1 - $2;      }
|   exp exp '*' {$$ = $1 * $2;      }
|   exp exp '/' {$$ = $1 / $2;      }
|   exp exp '^' {$$ = pow ($1, $2); }
|   exp 'n'     {$$ = -$1;         }
;
%%

/* The lexical analyzer */

int yylex (void)
{
    int c;

    /* Skip white space */
    while((c = getchar()) == ' ' || c == '\t')
        continue;
    /* Process numbers */
    if(c == '.' || isdigit (c))
    {
        ungetc (c, stdin);
        scanf ("%lf", $yylval);
        return NUM;
    }
    /* Return end-of-imput */
    if (c == EOF)
        return 0;
    /* Return a single char */
    return c;
}

int main (void)
{
    return yyparse ();
}

void yyerror (char const *s)
{
    fprintf (stderr, "%s\n", s);
}

Executing bison rpcalc.y in cmd returns the following error:

rpcalc.y:11.24-31: syntax error, unexpected {...}

What seems to be the problem?

1
According to the error message line 11 is giving a problem. That is the braces around { float }. What will happen if you remove the braces? - PapaAtHome
@PapaAtHome I tried. The cmd returns: rpcalc.y:11.24-29: syntax error, unexpected identifier - HDFighter
The %define api.value.type feature was introduced in bison 3.0. Type bison --version to check your version number. The error you are getting is what a version earlier than 3.0 would return for this statement, - Brian Tompsett - 汤莱恩
@Brian Tompsett - 汤莱恩 Yes that was the problem! Thank you very much Brian. I also checked the reference and found that the "{}" structure "has no meaning in earlier than 3.0.x versions of Bison" according to the official documentation. - HDFighter

1 Answers

1
votes

The fault is caused by you using features that are new to the 3.0 version of bison, whereas you have an older version of bison installed. If you are unable to upgrade to version 3.0, it is an easy change to convert the grammar to using the features of earlier versions of bison.

The %define api.value.type {double} can be changed to a %type command, and the %empty command removed. The resulting bison program would be:

/* Reverse polish notation calculator */

%{
    #include <stdio.h>
    #include <math.h>
    #include <ctype.h>
    int yylex (void);
    void yyerror (char const *);
%}

%type <double> exp
%token <double> NUM

%% /* Grammar rules and actions follow. */

input:
|   input line
;

line:
    '\n'
|   exp '\n'    {printf ("%.10g\n", $1);}
;

exp:
    NUM         {$$ = $1;          }
|   exp exp '+' {$$ = $1 + $2;      }
|   exp exp '-' {$$ = $1 - $2;      }
|   exp exp '*' {$$ = $1 * $2;      }
|   exp exp '/' {$$ = $1 / $2;      }
|   exp exp '^' {$$ = pow ($1, $2); }
|   exp 'n'     {$$ = -$1;         }
;
%%

/* The lexical analyzer */

int yylex (void)
{
    int c;

    /* Skip white space */
    while((c = getchar()) == ' ' || c == '\t')
        continue;
    /* Process numbers */
    if(c == '.' || isdigit (c))
    {
        ungetc (c, stdin);
        scanf ("%lf", $yylval);
        return NUM;
    }
    /* Return end-of-imput */
    if (c == EOF)
        return 0;
    /* Return a single char */
    return c;
}

int main (void)
{
    return yyparse ();
}

void yyerror (char const *s)
{
    fprintf (stderr, "%s\n", s);
}

This runs in a wider range of bison versions.