yacc and lex code for three address code statements - yacc

here is my lex code:
three.l
%{
#include "y.tab.h"
#include "string.h"
%}
%%
[a-zA-Z]+ { yylval.a_var=(char *)malloc(sizeof(char *));
strcpy(yylval.a_var,yytext);
return var;}
[-+/*,] {return yytext[0];}
[\t\n] return 0;
%%
my yacc is
three.y
%{
#include "stdio.h"
#include "string.h"
int yywrap()
{
return 1;
}
static int i;
int d;
char temp();
%}
%left '+' '-'
%left '*' '/'
%union{char *a_var;}
%token id
%token <a_var>var
%start line
%%
line:var '=' exp {printf("%c=t%c\n",$1,$3);}
;
exp:exp '+' exp {$$=temp();if(i<=1){printf("t%c=%c+%c\n",$$,$1,$3);} else{printf("t%c=t%c+%c\n",$$,$1,$3);} }
|exp '-' exp {$$=temp();if(i<=1){printf("t%c=%c-%c\n",$$,$1,$3); } else{printf("t%c=t%c-%c\n",$$,$1,$3);} }
|exp '*' exp {$$=temp();if(i<=1){printf("t%c=%c*%c\n",$$,$1,$3); } else{printf("t%c=t%c*%c\n",$$,$1,$3);} }
|exp '/' exp {$$=temp();if(i<=1){printf("t%c=%c/%c\n",$$,$1,$3); } else {printf("t%c=t%c/%c\n",$$,$1,$3);} }
|var {$$=$1;}
;
%%
main()
{
yyparse();
return 0;
}
int yyerror(char *s)
{
fprintf(stderr,"%s\n",s);
}
char temp()
{
return('1'+ i++);
}
but when i compile this
three.y:19.40-41: $3 of `line' has no declared type
three.y:21.20-21: $$ of `exp' has no declared type
three.y:21.60-61: $$ of `exp' has no declared type
three.y:21.63-64: $1 of `exp' has no declared type
three.y:21.66-67: $3 of `exp' has no declared type
three.y:21.100-101: $$ of `exp' has no declared type
three.y:21.103-104: $1 of `exp' has no declared type
three.y:21.106-107: $3 of `exp' has no declared type
three.y:22.21-22: $$ of `exp' has no declared type
three.y:22.61-62: $$ of `exp' has no declared type
three.y:22.64-65: $1 of `exp' has no declared type
three.y:22.67-68: $3 of `exp' has no declared type
three.y:22.104-105: $1 of `exp' has no declared type
three.y:22.107-108: $3 of `exp' has no declared type
three.y:23.22-23: $$ of `exp' has no declared type
three.y:23.62-63: $$ of `exp' has no declared type
three.y:23.65-66: $1 of `exp' has no declared type
three.y:23.68-69: $3 of `exp' has no declared type
three.y:23.102-103: $$ of `exp' has no declared type
three.y:23.105-106: $1 of `exp' has no declared type
three.y:23.108-109: $3 of `exp' has no declared type
three.y:24.21-22: $$ of `exp' has no declared type
three.y:24.61-62: $$ of `exp' has no declared type
three.y:24.64-65: $1 of `exp' has no declared type
three.y:24.67-68: $3 of `exp' has no declared type
three.y:24.102-103: $$ of `exp' has no declared type
three.y:24.105-106: $1 of `exp' has no declared type
three.y:24.108-109: $3 of `exp' has no declared type
three.y:25.10-11: $$ of `exp' has no declared type
pla help me to solve this..

add the line
%type <a_var> exp
to your code, you need to define the exp.

When you use a %union for your yystype, then when you refer to yylval you have to say which member of the union to use. So with your union
%union{char *a_var;}
when you say
line:var '=' exp {printf("%c=t%c\n",$1,$3);}
you should say instead something like $1.a_var:
line:var '=' exp {printf("%c=t%c\n",$1.a_var,$3.a_var);}

As far as I see, the types of the semantic values of line and exp seem not to be
specified in your code.
So, I think specifying the types like %type <a_var> line exp will solve
the error.
Hope this helps

Related

How to fix implicit declaration of function 'yyerror' problem

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.
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.)

how to fix integer out of range error :$3 error in YACC

I am developing a calculator using YACC and I receive this error :
Integer out of rang $3;
I have just now started learning yacc and can't rectify the error I can see the question already but no one has answered
%token NUMBER
%%
expr :expr '+'{$$ = $1 + $3;}
%%
#include<stdio.h>
#include "lex.yy.c"
yylex()
{
int c;
c=getchar();
if(isdigit(c))
{
yylval=c-'0';
return NUMBER;
}
return c;
}
int main()
{
yyparse();
return 1;
}
int yyerror(){
return 1;}
$3 refers to the 3rd term on the right side of the rule. In
expr :expr '+'{$$ = $1 + $3;}
there are only 2 terms on the right side of the production...

yacc $1 pass to variable in c?

I am working with lex and yacc, and I wonder how can I pass a value from $1 to a variable in c, in order to print it on the main?
file.y:
%{
#include <stdio.h>
%}
...
%token<num> NUM
%%
expression : NUM { printf("number:%d;\n", $1);}
;
%%
int main(){
yyparse();
printf("number is:%d;\n", var);
return 0;
}
doing something like '$1=var' to pass the value to the variable?

Bison Grammar %type and %token

Why is it that I have to use $<nVal>4 explicitly in the below grammar snippet?
I thought the %type <nVal> expr line would remove the need so that I can simply put $4?
Is it not possible to use a different definition for expr so that I can?
%union
{
int nVal;
char *pszVal;
}
%token <nVal> tkNUMBER
%token <pszVal> tkIDENT
%type <nVal> expr
%%
for_statement : tkFOR
tkIDENT { printf( "I:%s\n", $2 ); }
tkEQUALS
expr { printf( "A:%d\n", $<nVal>4 ); } // Why not just $4?
tkTO
expr { printf( "B:%d\n", $<nVal>6 ); } // Why not just $6?
step-statement
list
next-statement;
expr : tkNUMBER { $$ = $1; }
;
Update following rici's answer. This now works a treat:
for_statement : tkFOR
tkIDENT { printf( "I:%s\n", $2 ); }
tkEQUALS
expr { printf( "A:%d\n", $5 /* $<nVal>5 */ ); }
tkTO
expr { printf( "A:%d\n", $8 /* $<nVal>8 */ ); }
step-statement
list
next-statement;
Why is it that I have to use $<nVal>4 explicitly in the below grammar snippet?
Actually, you should use $5 if you want to refer to the expr. $4 is the tkEQUALS, which has no declared type, so any use must be explicitly typed. $3 is the previous midrule action, which has no value since $$ is not assigned in that action.
By the same logic, the second expr is $8; $6 is the second midrule action, which also has no value (and no type).
See the Bison manual:
The mid-rule action itself counts as one of the components of the rule. This makes a difference when there is another action later in the same rule (and usually there is another at the end): you have to count the actions along with the symbols when working out which number n to use in $n.

How to Read Multiple Lines of input file for arithmetic yacc program?

I am new to compilers and learning to make calculator that inputs multiple line equations (one equation each line) from a .txt file. And I am facing the problem of segmentation fault.
YACC Code :
%{
#include <stdio.h>
#include <string.h>
#define YYSTYPE int /* the attribute type for Yacc's stack */
extern int yylval; /* defined by lex, holds attrib of cur token */
extern char yytext[]; /* defined by lex and holds most recent token */
extern FILE * yyin; /* defined by lex; lex reads from this file */
%}
%token NUM
%%
Begin : Line
| Begin Line
;
Line : Calc {printf("%s",$$); }
;
Calc : Expr {printf("Result = %d\n",$1);}
Expr : Fact '+' Expr { $$ = $1 + $3; }
| Fact '-' Expr { $$ = $1 - $3; }
| Fact '*' Expr { $$ = $1 * $3; }
| Fact '/' Expr { $$ = $1 / $3; }
| Fact { $$ = $1; }
| '-' Expr { $$ = -$2; }
;
Fact : '(' Expr ')' { $$ = $2; }
| Id { $$ = $1; }
;
Id : NUM { $$ = yylval; }
;
%%
void yyerror(char *mesg); /* this one is required by YACC */
main(int argc, char* *argv){
char ch;
if(argc != 2) {printf("useage: calc filename \n"); exit(1);}
if( !(yyin = fopen(argv[1],"r")) ){
printf("cannot open file\n");exit(1);
}
yyparse();
}
void yyerror(char *mesg){
printf("Bad Expression : %s\n", mesg);
exit(1); /* stop after the first error */
}
LEX Code :
%{
#include <stdio.h>
#include "y.tab.h"
int yylval; /*declared extern by yacc code. used to pass info to yacc*/
%}
letter [A-Za-z]
digit [0-9]
num ({digit})*
op "+"|"*"|"("|")"|"/"|"-"
ws [ \t\n]
other .
%%
{ws} { /* note, no return */ }
{num} { yylval = atoi(yytext); return NUM;}
{op} { return yytext[0];}
{other} { printf("bad%cbad%d\n",*yytext,*yytext); return '?'; }
%%
/* c functions called in the matching section could go here */
I am trying to print the expression along with result.
Thanks In Advance.
In your parser, you have:
Line : Calc {printf("%s",$$); }
Now $$ is the semantic value which the rule is computing, and you haven't assigned anything to it. So it would not be unreasonable to assume that it is undefined, which would be bad, but in fact it does have a value because of the default rule $$ = $1;. All the same, it would be much more readable to write
printf("%s", $1);
But that's not correct, is it? After all, you have
#define YYSTYPE int
so all semantic types are integers. But you're telling printf that $1 is a string (%s). printf will believe you, so it will go ahead and try to dereference the int as though it were a char*, with predictable results (i.e., a segfault).
You are probably using a compiler which is clever enough to notice the fact that you are trying to print an int with a %s format code. But either you haven't asked the compiler to help you or you are ignoring its advice.
Always compile with warnings enabled. If you are using gcc or clang, that means putting -Wall in the command line. (If you are using some other compiler, find out how to produce warnings. It will be documented.) And then read the warnings and fix them before trying to run the program.
There are several other errors and/or questionable practices in your code. Your grammar is inaccurate (why do you use fact as the left-hand operand of every operator?), and despite your comment, your lexical scanner ignores newline characters, so there is no way the parser can know whether expressions are one per line, two per line, or spread over multiple lines; that will make it hard to use the calculator as a command-line tool.
There is no need to define the lex macro digit; (f)lex recognizes the Posix character class [[:digit:]] (and others, documented here) automatically. Nor is it particularly useful to define the macro num. Overuse of lex macros makes your program harder to read; it is usually better to just write the patterns out in place:
[[:digit:]]+ { yylval = atoi(yytext); return NUM; }
which would be more readable and less work both for you and for anyone reading your code. (If your professor or tutor disagrees, I'd be happy to discuss the matter with them directly.)