0
votes

Hi I am making a program that does simple arithmetic operations using Lex and yacc, but I am having a problem with a specific error.

ex1.y

%{
#include <stdio.h>
int sym[26];
%}

%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/' '%'

%%
program:
    program statement '\n'
    |
    ;

statement:
    expr            {printf("%d\n", $1);}
    | VARIABLE '=' expr {sym[$1] = $3;}
    ;

expr:
    INTEGER
    | VARIABLE      { $$ = sym[$1];}
    | expr '+' expr { $$ = $1 + $3;}
    | expr '-' expr { $$ = $1 - $3;}
    | expr '*' expr     { $$ = $1 * $3;}
    | expr '/' expr { $$ = $1 / $3;}
    | '(' expr ')'      { $$ = $2;}
    ;
%%

main() { return yyparse();}

int yyerror(char *s){
    fprintf(stderr,"%s\n",s);
    return 0;
}

ex1.l

%{
#include <stdlib.h>
#include "y.tab.h"
%}

%%

    /* variables */
[a-z]  {
        yylval = *yytext -'a';
        return VARIABLE;
    }
    
    /* integers */ 
[0-9]+ {
        yylval = atoi(yytext);
        return INTEGER;
    }

    /* operators */
[-+()=/*\n] { return *yytext;}

    /* skip whitespace */
[ \t]   ;

    /* anything else is an error */
.   yyerror("invalid character");

%%

int yywrap (void){
    return 1;
}

when I execute bellow instruction

$bison –d -y ex1.y

$lex ex1.l

$gcc lex.yy.c y.tab.c –o ex1

The following error occurs:

ex1.l: In function ‘yylex’:
ex1.l:28:1: warning: implicit declaration of function ‘yyerror’; did you mean ‘perror’? [-Wimplicit-function-declaration]
   28 | 
      | ^      
      | perror
y.tab.c: In function ‘yyparse’:
y.tab.c:1227:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration]
 1227 |       yychar = yylex ();
      |                ^~~~~
y.tab.c:1402:7: warning: implicit declaration of function ‘yyerror’; did you mean ‘yyerrok’? [-Wimplicit-function-declaration]
 1402 |       yyerror (YY_("syntax error"));
      |       ^~~~~~~
      |       yyerrok

I don't know what is wrong with my code. I would appreciate it if you could tell me how to fix the above error.

1

1 Answers

1
votes

The version of bison you are using requires you to declare prototypes for yylex() and yyerror. These should go right after the #include <stdio.h> at the top of the file:

    int yylex(void);
    int yyerror(char* s);

I would use int yyerror(const char* s) as the prototype for yyerror, because it is more accurate, but if you do that you'll have to make the same change in the definition.

You use yyerror in your lex file, so you will have to add its declaration in that file as well.

main() hasn't been a valid prototype any time this century. Return types are required in function declarations, including main(). So I guess you are basing your code on a very old template. There are better starting points in the examples in the bison manual. (And don't expect it to be easy to work with parser generators if you have no experience with C.)