Anonymoustez
Anonymoustez

Reputation: 41

Parsing a Simple Expression Statement

I am trying to build a parser for arithmetic expression using yacc. I have also included some semantic actions with it. But whenever I run the code it shows segmentation fault(core dumped). Please Help. This is my yacc file.

%{
#include <stdio.h>
#include <stdlib.h>
#include<string.h>

int yylex();
void yyerror(const char *s);
int temp[100];
char var[2]="t0";
char label[2]="L1";


%}

%union 
{
    struct attributes
    {
        char code[100];
        char addr[100];
        char op[2];

    }type_id;
        char ch;
}
%start L
%token ID NUM WHILE OR AND NOT True False Do end GE LE EE NE UMINUS
%right '='
%left AND OR
%left '<' '>' LE GE NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!' 
%type<type_id>L
%type<type_id>E 
%type<ch>ID 
%type<ch>NUM 




%%



%%

#include "lex.yy.c"

int main()
{
   printf("Enter the exp: ");
   yyparse();
}

This is my Lex file.

alpha [A-Za-z]
digit [0-9]
%%
[ \t\n]  
{digit}+    return NUM;
{alpha}({alpha}|{digit})*    return ID;
.    return yytext[0];
%%

When I compile my file I get this:

rome@rome-VirtualBox:~/Desktop/CompDesin$ gcc y.tab.c -ll -ly
test.y: In function ‘yyparse’:
test.y:48:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$3.code);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:49:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,"\n");
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:50:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$1);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:50:36: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast [-Wint-conversion]
                        strcat(temp,$1);
                                    ^
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:51:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,"=");
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:52:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$3.addr);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:53:52: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcpy($$.code,temp);
                                                    ^   
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘int *’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:60:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$1.code);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:61:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"\n");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:62:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$3.code);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:63:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"\n");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:64:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$$.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:65:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"=");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:66:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$1.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:67:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"+");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:68:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$3.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:69:53: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcpy($$.code,temp);
                                                     ^   
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘int *’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:74:53: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
                         strcpy($$.addr,$1);
                                                     ^
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:78:53: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
                         strcpy($$.addr,$1);
                                                     ^
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
rome@rome-VirtualBox:~/Desktop/CompDesin$ gcc y.tab.c -ll -ly
test.y: In function ‘yyparse’:
test.y:48:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$3.code);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:49:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,"\n");
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:50:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$1);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:50:36: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast [-Wint-conversion]
                        strcat(temp,$1);
                                    ^
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:51:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,"=");
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:52:31: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcat(temp,$3.addr);
                               ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:53:52: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
                        strcpy($$.code,temp);
                                                    ^   
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘int *’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:60:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$1.code);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:61:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"\n");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:62:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$3.code);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:63:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"\n");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:64:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$$.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:65:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"=");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:66:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$1.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:67:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,"+");
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:68:32: warning: passing argument 1 of ‘strcat’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcat(temp,$3.addr);
                                ^~~~
In file included from test.y:4:0:
/usr/include/string.h:129:14: note: expected ‘char * restrict’ but argument is of type ‘int *’
 extern char *strcat (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:69:53: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type [-Wincompatible-pointer-types]
                         strcpy($$.code,temp);
                                                     ^   
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘int *’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:74:53: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
                         strcpy($$.addr,$1);
                                                     ^
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~
test.y:78:53: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
                         strcpy($$.addr,$1);
                                                     ^
In file included from test.y:4:0:
/usr/include/string.h:121:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^~~~~~

And when I run my file i get this error:

rome@rome-VirtualBox:~/Desktop/CompDesin$ ./a.out
Enter the exp: a=b+c
Segmentation fault (core dumped)

Upvotes: 1

Views: 190

Answers (1)

Stephan Schlecht
Stephan Schlecht

Reputation: 27126

There are multiple problems:

  • there are several places where you provoke undefined behaviour.
  • lexer values are not stored correctly

Two notes:

  • keep in mind, that strings in C are terminated with a NUL byte and therefore the character arrays need to be dimensioned accordingly

  • for some of them the compiler warns you, it is a good idea to pay attention to the compiler warnings

Let's go through the different issues quickly:

  • Like Paul R and bruno noted correctly temp should be char array and the dimensions of var and label arrays are too small

  • then it still crashes, because ID and NUM are

defined as

%type<ch>ID 
%type<ch>NUM 

and ch is:

char ch;

in the %union statement.

The crashes occur because you define strcat(temp,$1); on line 50. $1 represents a single character, but your code tries to interpret this as a NUL-terminated string (char * pointer). You have similar cases on lines 74 and 78 with strcpy($$.addr,$1);. As mentioned earlier, the compiler warns you about this. This provokes undefined behavior, which in your case manifests itself in a segmentation error.

You could correct this e.g. to strncat(temp,&$1,1); to use only one character but in comments you write that your number of characters to be copied will differ and will depend on the input.

Therefore change the definition perhaps in %union to something like:

char strval[100];

Then adapt:

%type<strval>ID
%type<strval>NUM

Set the values in the scanner

It would no longer crash now, but it would not work as intended because the values are not set in the scanner. There only the type (ID or NUM) is determined, but the associated value is not set.

There it should look like:

{digit}+                     {
                                strcpy(yylval.strval, yytext);
                                return NUM;
                             }
{alpha}({alpha}|{digit})*    {
                                strcpy(yylval.strval, yytext);
                                return ID;
                             }

Scanner

You are currently including the "lex.yy.c" file in the .y file, like so:

#include "lex.yy.c"

I would rather do it the other way around. Remove it from there and instead make an include of the yacc generated "y.tab.h" in the .l file. So the beginning of the .l file could look like this:

%{
    #include "y.tab.h"
%}
alpha [A-Za-z]
...

The commands for building would be (might differ a little bit on your platform):

flex scanner.l
yacc -d grammar.y
cc -Wall -Wextra y.tab.c lex.yy.c -ll

Finally, an input like

a=bb+c+4711

would produce an output like:

t0=bb+c
t1=t0+4711

Further possible improvements

Once this works as desired, you can either think about dynamically allocating memory for values, as recommended by rici in the comments section, or limit the length of values to ensure that they are not written beyond the end of fixed-size buffers.

Upvotes: 2

Related Questions