2
votes

I am having a problem which I am unable to figure out. I have two files, lexer.l and parser.y (for tokens and grammar+three address code). I am compiling the files on linux using:

yacc -d parser.y
lex lexer.l

Which gives me lex.yy.c and y.tab.c and y.tab.h files.

However, when I'm trying to compile them together for a sample file for which I am trying to build the language for (input.txt) like:

gcc y.tab.c lex.yy.c -lfl -o example

I am getting the following warning:

parser.y:963:6: warning: conflicting types for ‘yyerror’
 void yyerror(const char *s) {
      ^~~~~~~
y.tab.c:2333:7: note: previous implicit declaration of ‘yyerror’ was here
       yyerror (YY_("syntax error"));
       ^~~~~~~

And when I am trying to execute the 'example' object file, I am getting the error:

{EEK, parse error!  Message: syntax error

It shows that the program is getting stuck in yyerror function created in parser.y (at the bottom). I am not sure why it is messing up in y.tab.c file. All I want is to successfully execute 'example' object file for a sample (input.txt). But the program seems to get stuck in yyerror I guess. Also I am new to using lex and yacc. Is there a way to get rid of this error? Any help will be appreciated. Thank you.

lexer.l

/*Lex File*/
%{
#include <stdio.h>
#include <string.h>

#include "y.tab.h"

char c;


%}

DIGIT  [0-9]+
NUMBER [+-]?[0-9]+|[+-]?[0-9]*"."[0-9]+
STRING \"(\\.|[^\"])*\"
BOOLEAN ["True" "False"]
ID [a-zA-Z_][0-9a-zA-Z_]*
FLOAT [0-9]+[.][0-9]*

ARITHMETIC_OPERATORS ['+' '-' '*' '/']
OTHER_CHARACTERS ['=' '.' '(' ')' '{' '}' '[' ']']
TYPES ["Number" "String" "Boolean" "Return"]

%%
[ \t] ;
[\n] ;


"If"    { return (IF); }
"Else"  { return (ELSE); }
"While" { return (WHILE); }
"Main()" {return (MAIN); }
"Read()" {return (READ);}
"Class"  {return (CLASS);}

"Number" {return (TYPES);}
"String" {return (TYPES);}
"Boolean" {return (TYPES);}
"Print"   {return (PRINT);}
"Return"  {return (TYPES);}


"<!--".*"--!>" ;


">" {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"<" {yylval.sval = strdup(yytext);
        return (REL_OPT);}
">="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"<="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"!="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"=="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}

"|" {yylval.sval = strdup(yytext);
        return (OR);}
"&" {yylval.sval = strdup(yytext);
        return (AND);}
"!" {yylval.sval = strdup(yytext);
        return (NOT);}

{NUMBER}  { yylval.nval = atof(yytext);
       return NUMBER; }

{BOOLEAN}  { yylval.sval = yytext;
       return BOOLEAN; }

{STRING}  { yylval.sval = yytext;
       return STRING; }

{ID} {
        yylval.sval = strdup(yytext);
        return ID; 
}
{ARITHMETIC_OPERATORS}   {
                c = yytext[0];
                 return(c);
              }

{OTHER_CHARACTERS}   {
                 c = yytext[0];
                 return(c);
              }

%%

parser.y

/*Yacc File with semantics*/

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
char *s1, *s2;
char *b1, *b2;

struct exprType{

    char *addr;
    char *code;
};


int n=1;
int nl = 1;
char *var;
char num_to_concatinate[10];
char num_to_concatinate_l[10];
char *ret;
char *temp;

char *label;
char *label2;
char *check;

char *begin;

struct exprType *to_return_expr;

char * newTemp(){

    char *newTemp = (char *)malloc(20);
    strcpy(newTemp,"t");
    snprintf(num_to_concatinate, 10,"%d",n);
    strcat(newTemp,num_to_concatinate);

    n++;
    return newTemp;
}

char * newLabel(){

    char *newLabel = (char *)malloc(20);
    strcpy(newLabel,"L");
    snprintf(num_to_concatinate_l, 10,"%d",nl);
    strcat(newLabel,num_to_concatinate_l);

    nl++;
    return newLabel;
}
%}

%start startSym

%union {
    float nval;
    char *sval;
    struct exprType *EXPRTYPE;
}


%token <nval> NUMBER
%token <sval> BOOLEAN
%token <sval> STRING
%token <sval> READ
%token <sval> PRINT
%token <sval> ID IF ELSE WHILE TYPES REL_OPT OR AND NOT MAIN CLASS TRUE FALSE
%token <sval> '+' '-' '*' '/' '\n' '=' '.'
%type <sval> list text construct block dec bool program startSym
%type <EXPRTYPE> expr stat


%left OR
%left AND
%left NOT
%left REL_OPT
%right '='
%left '+' '-'
%left '*' '/' '%'


%%

startSym:   program 
            {
                s1 = $1;

                label = newLabel();
                check = strstr(s1, "NEXT");

                while(check != NULL) {
                    strncpy(check, label, strlen(label));
                    strncpy(check + strlen(label),"    ", (4 - strlen(label)));
                    check = strstr(s1, "NEXT");
                }

                ret = (char*) malloc(strlen(s1) + 10);
                ret[0] = 0;

                strcat(ret, s1);
                strcat(ret, "\n");
                strcat(ret, label);
                strcat(ret, "3AD ends here\n");

                printf("\nIntermediate code:\n");
                puts(ret);

                $$ = ret;
            }

        ;

program :   program construct 
        {  
            s1 = $1;
            s2 = $2;

            label = newLabel();

            check = strstr(s1, "NEXT");

            while(check != NULL) {
                strncpy(check, label, strlen(label));
                strncpy(check + strlen(label), "    ", (4 - strlen(label)));
                check = strstr(s1, "NEXT");
            }

            ret = (char*) malloc(strlen($1) + strlen($2) + 4);
            ret[0] = 0;
            strcat(ret, $1);
            strcat(ret, "\n");
            strcat(ret, label);
            strcat(ret, " : ");
            strcat(ret, $2);

            printf("Program construct\n");


            puts(ret);
            $$ = ret;

        }
        |
        construct
            {
            printf("Final construct \n");
            puts($1);
            $$ = $1;
            }
        |
        list
            {
            printf("Final list \n");
            puts($1);
            $$ = $1;
            }
        ;

construct :     block
        {
            $$ = $1;
        }
        |
        WHILE '(' bool ')' block
        {
            printf("Inside WHILE\n");
            puts($5);
            b1 = $3;
            s1 = $5;

            begin = newLabel();
            label = newLabel();

            check = strstr(b1, "TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,"NEXT",4);
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            check = strstr (s1,"NEXT");

            while(check!=NULL){
                strncpy (check,begin,strlen(begin));
                strncpy (check+strlen(begin),"    ",(4-strlen(begin)));
                check = strstr (s1,"NEXT");
                }

            ret = (char *)malloc(strlen(b1)+strlen(s1)+20);
            ret[0] = 0;
            strcat(ret,begin);
            strcat(ret," : ");
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,s1);

            strcat(ret,"\n");
            strcat(ret,"goto ");
            strcat(ret,begin);

            printf("Final return from WHILE\n");
            puts(ret);

            $$ = ret;
        }


        |
        IF '(' bool ')' block
        {
            printf("Inside IF\n");

            label = newLabel();
            b1 = $3;

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,"NEXT",4);
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            ret = (char *)malloc(strlen(b1)+strlen($5)+4);
            ret[0] = 0;
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,$5);

            puts(ret);
            $$ = ret;

        }

        |
        IF '(' bool ')' block ELSE block
        {
            printf("Inside IF then ELSE\n");

            b1 = $3;
            label = newLabel();

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
            }

            label2 = newLabel();
            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label2,strlen(label2));
                strncpy (check+strlen(label2),"    ",(4-strlen(label2)));
                check = strstr (b1,"FAIL");
            }

            ret = (char *)malloc(strlen(b1)+strlen($5)+strlen($7)+20);
            ret[0] = 0;
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,$5);
            strcat(ret,"\n");
            strcat(ret,"goto NEXT");
            strcat(ret,"\n");
            strcat(ret,label2);
            strcat(ret," : ");
            strcat(ret,$7);

            puts(ret);

            $$ = ret;



        }

        | 
        CLASS ID block
        {



               $$ = $3;

        }
        ;

block:  '{' list '}'
        {
                printf("Inside class block\n");
                $$ = $2;
        }

        |

        '{' construct '}'
        {
                $$ = $2;
        }
        |

        '[' list ']'
        {
                printf("Inside specific block\n");
                $$ = $2;
        }

        |
        '[' construct ']'
        {
                $$ = $2;
        }

        ;


list:    stat               
        {
            $$ = $1->code;
        }
        |

        list stat
        {
            ret = (char*) malloc(strlen($1) + strlen($2->code) + 4);
            ret[0] = 0;

            strcat(ret, $1);
            strcat(ret, "\n");
            strcat(ret, $2->code);

            printf("Inside list stat \n");
            puts(ret);
            $$ = ret;
        }

       |
        list error '\n'
        {
            yyerrok;
        }

        |
        MAIN block
        {


            $$ = $2;

        }
        ;


stat:    '.'
        {


          to_return_expr = (struct exprType*) malloc(sizeof(struct exprType));

          to_return_expr->addr = (char *) malloc(20);
          to_return_expr->addr = $1;

          to_return_expr->code = (char*) malloc(2);
          to_return_expr->code[0] = 0;

          $$ = to_return_expr; 
        }

        |
        expr '.'
        {
            $$ = $1;

        } 
        |

        dec '.'
        {
         to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;   
        }
        |

        text '=' expr '.'
        {
            printf("Assignment statement \n");

            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
            to_return_expr->addr = (char *)malloc(20);
            to_return_expr->addr = newTemp();

            ret = (char*)malloc(20);
            ret[0] = 0;

            strcat(ret, $1);
            strcat(ret, "=");
            strcat(ret, $3->addr);
            printf("RET = \n");
            puts(ret);

            temp = (char*) malloc(strlen($3->code) + strlen(ret) + 6);

            temp[0] = 0;

            if($3->code[0] != 0) {
                strcat(temp, $3->code);
                strcat(temp, "\n");
            }
            strcat(temp, ret);
            printf("TEMP = \n");

            puts(temp);

            to_return_expr->code = temp;

            $$ = to_return_expr;
        }

        |

        dec '=' expr '.'
        {

        printf("Dec and Assignment statement \n");
        to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,$1);
        strcat(ret,"=");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
        }


        ;

dec :   TYPES text 
        {   
            $$ = $2;
        }
        ;

bool :  expr REL_OPT expr
        {
            printf("Inside rel opt\n");

            temp = (char *)malloc(strlen($1->code)+strlen($3->code)+50);
            temp[0] = 0;

            if($1->code[0]!=0){
                strcat(temp,$1->code);
                strcat(temp,"\n");
                }
            if($3->code[0]!=0){
                strcat(temp,$3->code);
                strcat(temp,"\n");
                }

            ret = (char *)malloc(50);
            ret[0] = 0;
            strcat(ret,"if(");
            strcat(ret,$1->addr);
            strcat(ret,$2);
            strcat(ret,$3->addr);
            strcat(ret,") goto TRUE \n goto FAIL");

            strcat(temp,ret);

            $$ = temp;
        }

        |
        bool OR bool
        {
            printf("Inside OR\n");
            b1 = $1;
            b2 = $3;

            label = newLabel();

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            temp = (char *)malloc(strlen(b1)+strlen(b2)+10);
            temp[0] = 0;

            strcat(temp,b1);
            strcat(temp,"\n");
            strcat(temp,label);
            strcat(temp," : ");
            strcat(temp,b2);

            $$ = temp;
        }

        |
        bool AND bool
        {
            printf("Inside AND\n");

            b1 = $1;
            b2 = $3;

            label = newLabel();

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            temp = (char *)malloc(strlen(b1)+strlen(b2)+10);
            temp[0] = 0;

            strcat(temp,b1);
            strcat(temp,"\n");
            strcat(temp,label);
            strcat(temp," : ");
            strcat(temp,b2);

            $$ = temp;
        }

        |
        NOT '(' bool ')'
        {
            printf("Inside NOT\n");
            b1 = $3;
            label = "TEFS";

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            label = "TRUE";
            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            label = "FAIL";
            check = strstr (b1,"TEFS");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TEFS");
                }
            $$ = b1;
        }

        |
        '(' bool ')'
        {
            $$ = $2;
        }




        ;

expr:    '(' expr ')'
         {
           $$ = $2;
         }

         |

         expr '*' expr
         {

           printf("Multiplication : ");

           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"*");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

        $$ = to_return_expr;


         }

         |
         expr '/' expr
          {

           printf("Division: ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"/");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

        $$ = to_return_expr;
        }

         |
         expr '+' expr
         {


           printf("Addition : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Addition : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"+");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
         }

         |

         expr '-' expr
        {


           printf("Subtraction : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Subtraction : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"-");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
        }

        |
        text
        {


           printf("Text : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Text : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;
        }

        |
        BOOLEAN
        {


          // printf("Inside BOOLEAN : %s\n",$1);

            printf("Inside BOOLEAN : %s\n",$1);
        //$$ = $1;

        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;
        }

        |

        STRING
        {


           /*printf("Inside String : ");
          printf("Inside STRING : %s\n",$1);
        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;*/


            printf("Inside STRING : %s\n",$1);
        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;
        //$$ = $1;



        }

        |

        NUMBER
        {





            printf("Inside NUMBER : %f\n",$1);
        //$$ = $1;

        var = (char *)malloc(20);
            snprintf(var, 10,"%f",$1);

        $$ = var;
        }

        |
        READ
        {

                /*printf("Inside Read: \n");
                to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;*/

                printf("Inside Read: \n");
                var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;

        }
        ;

text:   ID
        {


           printf("Inside Identifier : ");



           $$ = $1;
        }

        ;


%%

extern int yylex();
extern int yyparse();
extern FILE *yyin;

main() {
    // open a file handle to a particular file:
    FILE *myfile = fopen("input.txt", "r");
    // make sure it is valid:
    if (!myfile) {
        printf("I can't open a.snazzle.file!");
        return -1;
    }
    // set lex to read from it instead of defaulting to STDIN:
    yyin = myfile;

    // parse through the input until there is no more:
    do {
        yyparse();
    } while (!feof(yyin));

}

void yyerror(const char *s) {
    printf("EEK, parse error!  Message: ");
    puts(s);
    //printf("\n");
    // might as well halt now:
    exit(-1);
}

input.txt

Class ABC {

    Main() [

        Number a = 8.

        Return 0.

    ]
}
1

1 Answers

1
votes

The problem is simply, that you did not declare the yyerror() function before it is used. So the implicit declaration is returning int, while your function is defined to return void, which leads to the conflicting types error.

The solution is, to declare your yyerror()-function at the top of the file, i.e. here:

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
char *s1, *s2;
char *b1, *b2;
void yyerror(const char *s);

That should fix this error.

For debugging your parse error, you can invoke yacc with the -t option and declare the variable

int yydebug = 1;

at the top of your file. The parser will then output state information for each token read. In this case, the problem is that your lexer rules are incorrect, especially the regular expressions:

BOOLEAN ["True" "False"]
ARITHMETIC_OPERATORS [+*/-]
OTHER_CHARACTERS [=.(){}\[\]]
TYPES ["Number" "String" "Boolean" "Return"]

should be

 BOOLEAN (True|False)
 ARITHMETIC_OPERATORS [+*/-]
 OTHER_CHARACTERS [=.()\{\}\[\]]
 TYPES (Number|String|Boolean|Return)

There are several examples available for flex definition files, which might give you an idea how the regular expressions have to look like.