What does return 0 do in the code and why is the yywrap function written without a body? - yacc

I AM USING BISON AND FLEX.
What does return 0 do in case of the kcalc.l file that I have posted?
And I am not getting the use of yywrap without a body (i mean not literally but an empty body).The code is of a calculator without any variable managing and basic operations that can be done like addition subtraction multiplication division and handling of unary minus operator. I have been studying through the lex and yacc specifications but did not get any answer for the query I asked .
Kcal.y
%{
#include <stdio.h>
%}
%token Number
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%%
statement: expression
{ printf(" result = %d\n", $1);} ;
expression: expression '+' expression
{ $$ = $1 + $3;
printf("Recognised'+'expression\n");
}
| expression '-' expression
{ $$ = $1 - $3;
printf("Recognised '-' expression\n");
}
| expression '*' expression
{ $$ = $1 * $3;
printf("Recognised '*' expression\n");
}
| expression '/' expression
{ if ($3 == 0)
printf ("divide by zero\n");
else
$$ = $1 / $3;
printf("Recognised '/' expression\n");
}
| '-' expression %prec UMINUS
{
$$ = - $2;
printf("Recognised paranthesized expression\n");
}
| '(' expression ')'
{
$$ = $2;
printf("Recognised paranthesized expression");
}
| Number { $$ = $1;
printf("Recognised a no.\n");
}
;
%%
int main(void)
{
return yyparse();
}
int yyerror (char *msg)
{
return fprintf(stderr,"Yacc :%s", msg);
}
yywrap()
{
}
 
kcalc.l
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ { yylval = atoi(yytext);
printf("accepted the number : %d\n", yylval);
return Number; }
[ \t] { printf("skipped whitespace \n");}
\n { printf("reached end of line\n");
**return 0;**
}
. { printf("found other data \" %s\n", yytext);
return yytext[0];
}
%%

The return 0 notifies the end-of-input to the parser, so apparently the expression should be contained on a single line. The empty body of yywrap is just wrong. If you use -Wall with the gcc compiler it will give two warnings for yywrap:
kcal.y:54: warning: return type defaults to ‘int’
kcal.y:55: warning: control reaches end of non-void function
The first one because no result type for the function is specified (K&R style C), so it is assumed it should return an int. The second warning because it lacks a return statement for such an int.
Since a newline terminates the input, the chances of yywrap ever being called are slim. But it will be called if the input does not contain a newline. If by sheer accident the (more or less random) return value of yywrap were to be interpreted as 0 the tokenizer would end up in an infinite loop of repeatedly calling yywrap.

Related

Using yacc to output boolean expressions

I am trying to learn this language for a college class and our teacher gave us a prompt to try. Basically we are to take a boolean expression and output if that expression is true or false. The input will be in the format of:
true and (false or true) or false.
I have talked with my professor about many solutions and he is wanting the class to make tokens for AND OR NOT TRUE FALSE. He also wants us to use the logical operators in the yacc file instead of the tokens, IE ||, &&, !.
test.l
%{
#include "y.tab.h"
%}
AND [Aa][Nn][Dd]
OR [Oo][Rr]
NOT [Nn][Oo][Tt]
op '&' | '|' | "!"
%%
[a-zA-Z] {return ALPHA;}
[\t]+ ;
[\n] {return '\n';}
{AND} { return (AND); }
{OR} { return (OR); }
{NOT} { return (NOT); }
[Tt][Rr][Uu][Ee] { yylval = 1;
return (boolean); }
[Ff][Aa][Ll][Ss][Ee] { yylval = 0;
return (boolean); }
. {();}
%%
test.y
%{
#include<stdio.h>
#include<stdlib.h>
int yylex();
%}
%token ALPHA AND OR NOT TRUE FALSE boolean
%left "&" "|"
%right '!'
%%
program: bexpr '\n' {if ($1 >= 1)
{
printf("TRUE\n");
exit(0);
}
else{
printf("FALSE\n");
exit(0);
}
|
;
bexpr: bexpr "|""|" bterm { $$ = $1 || $3; }
| bterm { $$ = $1; }
;
bterm: bterm "&""&" bfactor { $$ = $1 && $3; }
| bfactor { $$ = $1; }
;
bfactor: '!' bfactor { $$ = ! $2; }
| '(' bexpr ')' { $$ = $2; }
| TRUE { $$ = $1; }
| FALSE {$$ = $1; }
| boolean { $$ = $1; }
;
%%
int main()
{
printf("Enter your truth statement\n");
yyparse();
return 0;
}
If i were to put in true and false, would expect false. However, I get syntax error. If I only put in true, the output is correct, same for false. Basically if I put anything other than one term, the program throws an error.

Yacc %define parse.error verbose generates error

When I try to get more out of my "syntax error", I seem to use the way described on so many websites, but all seem to create their own errors, for some reason.
I was getting standard "syntax error" on line 5 of the Input file... so I wanted to add better error handling so I can see what exactly is the issue. But
%define parse.error verbose
However, it gives me this;
error: %define variable 'parse.error' is not used
Below are my files, as long as you keep it constructive, feel free to comment on more then just the error parts, any help is welcome :)
(As long as the errors get fixed as well :P )
Thanks in advance!
lex file;
%option nounput yylineno
%{
#include "yaccTest.tab.h"
void InvalidToken();
void extern yyerror (char *s);
%}
whitespace [ \t\r\v\f]
linefeed \n
%%
";" {return SEMICOLON;}
"=" {return EQ;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULTIPLY;}
"/" {return DEVIDE;}
"(" {return BO;}
")" {return BC;}
"^" {return POWER;}
"print" {return PRINT;}
[a-zA-Z][a-zA-Z0-9]* {yylval.charValue = yytext[0]; return IDENTIFIER;}
[0-9]+ {yylval.intValue = atoi(yytext); return NUMBER;}
{whitespace} {;}
. {InvalidToken();}
%%
void yyerror(char *s) {
fprintf(stderr, "\nERROR ON LINE %d : \n %s\n", yylineno, s);
exit(0);
}
void InvalidToken(){
printf("ERROR ON LINE %d : \n Invalid Token %s\n", yylineno,yytext);
exit(0);
}
int yywrap (void) {return 1;}
yacc file;
%{
#include <stdio.h>
#include <stdlib.h>
int getVariableValue(char varID);
extern int yylineno;
int varIDs[52] = {0};
int varValues[52] = {0};
%}
%define parse.lac full
%define parse.error verbose
%union YYSTYPE {int intValue; char charValue;}
%token COLON SEMICOLON ST SE EQ GE GT PLUS MINUS MULTIPLY DEVIDE BO BC CBO CBC POWER LOOP PRINT
%token <intValue> NUMBER
%token <charValue> IDENTIFIER CHAR
%type <charValue> declaration expression
%type <intValue> numval
%right EQ
%left PLUS MINUS
%left MULTIPLY DEVIDE
%left POWER
%%
declaration : IDENTIFIER EQ expression
| declaration IDENTIFIER EQ expression
;
expression : numval SEMICOLON
| PRINT BO numval BC SEMICOLON {printf("Printing");}
;
numval : NUMBER {$$ = $1;}
| NUMBER PLUS NUMBER {$$ = $1 + $3;}
| NUMBER MINUS NUMBER {$$ = $1 - $3;}
| NUMBER MULTIPLY NUMBER {$$ = $1 * $3;}
| NUMBER DEVIDE NUMBER {$$ = $1 / $3;}
| NUMBER POWER NUMBER {int i;int j = $1;for(i = 1; i < $3; i++){j=j*$1;};$$ = j;}
;
%%
int getVariableValue(char varID) {
int i, j, localTemp;
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (varID == varIDs[i]) {
localTemp = varValues[i];
}
}
return localTemp;
}
int setVariableValue(char varID, int varValue) {
int i, varPresent = 0;
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (varID == varIDs[i]) {
varValues[i] = varValue;
varPresent = 1;
}
}
if (varPresent == 0) {
for (i=0;i<((sizeof(varIDs)/sizeof(varIDs[0])));i++) {
if (&(varIDs[i]) == NULL) {
if (&(varValues[i]) == NULL) {
varIDs[i] = varID;
varValues[i] = varValue;
}
else {
missingVarIDError(varID, varValue);
}
}
else {
notEnoughStorageError(varID, varValue);
}
}
}
}
int missingVarIDError(char *id, int val){
printf("\nERROR ON LINE %d : \nIdentifier '%s' not found, but assigned location DOES have a value; %s",yylineno,id,val);
exit(0);
}
int notEnoughStorageError(char *id, int val){
printf("\nERROR ON LINE %d : \nIdentifier '%s' did not fit in StorageArray, '%3' not stored!",yylineno,id,val);
exit(0);
}
int main (void) {
return yyparse ( );
return 0;
}
Input file;
x=4;
y=2+6;
X=2;
z=5;
print(4);

lex and yacc to parse trignometric expression

I have the following code for lex and yacc. I am getting kind of extra values in the printed statement can anyone tell. whats wrong with the code?
Lex code:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
[ \t] ;
[+-] { yylval=yytext; return Sym;}
(s|c|t)..x { yylval=yytext; return Str;}
[a-zA-Z]+ { printf("Invalid");}
%%
int yywrap()
{
return 1;
}
yacc code:
%{
#include<stdio.h>
%}
%start exps
%token Sym Str
%%
exps: exps exp
| exp
;
exp : Str Sym Str {printf("%s",$1); printf("%s",$2); printf("%s",$3);}
;
%%
int main (void)
{
while(1){
return yyparse();
}
}
yyerror(char *err) {
fprintf(stderr, "%s\n",err);
}
Input:
sinx+cosx
output:
sinx+cosx+cosxcosx
look at the output of the code!!!
yytext is a pointer into flex's internal scanning buffer, so its contents will be modified when the next token is read. If you want to return it to the parser, you need to make a copy:
[+-] { yylval=strdup(yytext); return Sym;}
(s|c|t)..x { yylval=strdup(yytext); return Str;}
Where symbols are a single character, it might make more sense to return that character directly in the scanner:
[-+] { return *yytext; }
in which case, your yacc rules should use the character directly in '-single quotes:
exp : Str '+' Str {printf("%s + %s",$1, $3); free($1); free($3); }
| Str '-' Str {printf("%s - %s",$1, $3); free($1); free($3); }

lex and yacc : a simple calculator with syntax error

a simple calculator support only + - * / and integer. I use GNU/Linux.
hoc1.l:
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[ \t] { ; }
[0-9]+ { sscanf(yytext, "%d", &yylval); printf("\nget %d\n", yylval); return NUMBER; }
\n {return 0;}
%%
int yywrap(void) {
return 1;
}
hoc1.y
%{
#include<stdio.h>
#define YYSTYPE int
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
list:
| list '\n'
| list expr '\n' {printf("\t%d\n",$2);}
;
expr: NUMBER { $$ = $1; }
| expr '+' expr {$$ = $1+$3;}
| expr '-' expr {$$ = $1-$3;}
| expr '*' expr {$$ = $1*$3;}
| expr '/' expr {$$ = $1/$3;}
;
%%
int main(void)
{
yyparse();
return 0;
}
int yyerror(char *s) {
fprintf(stderr, "*%s*\n", s);
return 0;
}
runtime-error:
% ./hoc
8+9
get 8
+
get 9
*syntax error*
why and how to sovle it, thx!
You forgot to include your operators in your lex file, and you should return nonzero on a successful token read: returning 0 intuitively means there was no match by yylex. Remove the line in your lex file handling the newline character and replace it with the following:
[-+*/\n] { return *yytext; }
. { yyerror("unrecognized character"); return 0; }
Now it should work. Returning *yytext allows your yacc grammar to parse an expression successfully, e.g. if you get a '+', return it to allow the grammar to parse properly.

What's wrong with this yacc file?

When I run yacc -d parser.y on the following file I get the following errors:
parser.y:23.3-24.4: warning: unused value: $4
15 rules never reduced
parser.y: warning: 7 useless nonterminals and 15 useless rules
parser.y:16.1-14: fatal error: start symbol statement_list does not derive any sentence
make: *** [y.tab.c] Error 1
I'm particularly concerned about how to get rid of the fatal error.
%{
#include "parser.h"
#include <string.h>
%}
%union {
double dval;
struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
%type <dval> expression
%type <dval> term
%type <dval> factor
%%
statement_list: statement '\n'
| statement_list statement '\n'
;
statement: NAME '=' expression { $1->value = $3; }
| expression { printf("= %g\n", $1); }
;
expression: expression '+' term { $$ = $1 + $3; }
| expression '-' term { $$ = $1 - $3; }
term
;
term: term '*' factor { $$ = $1 * $3; }
| term '/' factor { if($3 == 0.0)
yyerror("divide by zero");
else
$$ = $1 / $3;
}
| factor
;
factor: '(' expression ')' { $$ = $2; }
| '-' factor { $$ = -$2; }
| NUMBER
| NAME { $$ = $1->value; }
;
%%
/* look up a symbol table entry, add if not present */
struct symtab *symlook(char *s) {
char *p;
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++) {
/* is it already here? */
if(sp->name && !strcmp(sp->name, s))
return sp;
if(!sp->name) { /* is it free */
sp->name = strdup(s);
return sp;
}
/* otherwise continue to next */
}
yyerror("Too many symbols");
exit(1); /* cannot continue */
} /* symlook */
yyerror(char *s)
{
printf( "yyerror: %s\n", s);
}
All those warnings and errors are caused by the missing | before term in your expression rule. The hint is the unused $4 in a snippet that's plainly should only have 3 arguments. That problem cascades into all the others.
Change:
expression: expression '+' term { $$ = $1 + $3; }
| expression '-' term { $$ = $1 - $3; }
term
;
into:
expression: expression '+' term { $$ = $1 + $3; }
| expression '-' term { $$ = $1 - $3; }
| term
;
and try again.
you forget the or | here
expression: expression '+' term { $$ = $1 + $3; }
| expression '-' term { $$ = $1 - $3; }
term
;
the last rule should be |term {};