1

I am trying to display the whole arithmetic expression from text file and its result, I tried it with file handling option but it is not working.

YACC :

%{
#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

%%

Calc  : Expr               {printf(" = %d\n",$1);} 
  | Calc Expr          {printf(" = %d\n",$2);}
  | Calc error         {yyerror("\n");}
  ;
Expr  : Term               { $$ = $1;         }
  | Expr '+' Term      { $$ = $1 + $3;    }
  | Expr '-' Term      { $$ = $1 - $3;    }
  ;
Term  : Fact               { $$ = $1;         }
  | Term '*' Fact      { $$ = $1 * $3;    }
  | Term '/' Fact      { if($3==0){ 
                yyerror("Divide by Zero Encountered.");
            break;}
               else
                $$ = $1 / $3;    
                   }
  ;
Fact  : Prim               { $$ = $1;        }
  | '-' Prim           { $$ = -$2;       }
  ;      
Prim  : '(' Expr ')'       { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
Id    :NUM                 { $$ = yylval;    }
  ;
%%

void yyerror(char *mesg); /* this one is required by YACC */

main(int argc, char* *argv){
char ch,c;
FILE *f;    
if(argc != 2) {printf("useage:  calc filename \n"); exit(1);}
if( !(yyin = fopen(argv[1],"r")) ){ 
       printf("cannot open file\n");exit(1);
 }
/*  
 f=fopen(argv[1],"r");
 if(f!=NULL){
char line[1000];
while(fgets(line,sizeof(line),f)!=NULL)
    {
            fprintf(stdout,"%s",line);
        yyparse();
    }

}
*/
yyparse();
}

void yyerror(char *mesg){
printf("\n%s", mesg);
}

LEX

%{
#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])*
op      "+"|"*"|"("|")"|"/"|"-"
ws      [ \t\n\r]+$
other   .

%%

{ws}    {  /*Nothing*/ }
{digit} {  yylval = atoi(yytext); return NUM;}
{op}    {  return yytext[0];}
{other} {  printf("bad%cbad%d\n",*yytext,*yytext); return  '?'; }

%%

My Text file contains these two expressions :

4+3-2*(-7)
9/3-2*(-5)

I want output as :

4+3-2*(-7)=21
9/3-2*(-5)=13

But the Output Is :

=21
=13

because a parser will do all calculations at once so this (the commented code) is not legit to use. So what is needed is to show pass input expression to grammar and print in Calc block. I am not able to find anything relevant on google about displaying input in grammar.Thanks in advance for comments & suggestions.

Nikul Vyas
  • 363
  • 3
  • 7
  • 30
  • You don't say in what way it's not working. Give us a clue. – Emacs User Feb 14 '17 at 02:10
  • I want an output like 9/3-2*(-5)=13 but it is only possible if the grammar will fetch the output. – Nikul Vyas Feb 14 '17 at 02:14
  • Still does not help. You say you are not finding anything relevant on google. What do you consider relevant. What did you search for? Update your question with details instead of commenting here. – Emacs User Feb 14 '17 at 02:20
  • Emacs I have updated. – Nikul Vyas Feb 14 '17 at 02:37
  • I don't have a solution, but a suggestion: why not keep an array var for each line of *f and then when you return yytext{0}, append that line before returning. Do it in a loop so you can skip for the lines with error conditions. – Emacs User Feb 14 '17 at 02:58

2 Answers2

0

You don't want to do this in the grammar. Too complicated, and too subject to whatever rearrangement the grammar may do. You could consider doing it in the lexer, i.e. print yytext in every action other than the whitespace action, just before you return it, but I would echo all the input as it is read, by overriding lex(1)'s input function.

NB You should be using flex(1), not lex(1), and note that if you change, yyyext ceases being a char[] and becomes a char *.

I didn't mention it in your prior question, but this rule:

{other} {  printf("bad%cbad%d\n",*yytext,*yytext); return  '?'; }

would better be written as:

{other} {  return yytext[0]; }

That way the parser will see it and produce a syntax error, so you don't have to print anything yourself. This technique also lets you get rid of the rules for the individual special characters +,-=*,/,(,), as the parser will recognize them via yytext[0].

user207421
  • 305,947
  • 44
  • 307
  • 483
-1

Finally, I got it :

YACC

%{
#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

%%

Calc  : Expr               {printf(" = %d\n",$1);} 
  | Calc Expr          {printf(" = %d\n",$2);}
  | error              {yyerror("Bad Expression\n");}
  ;

Expr  : Term               { $$ = $1;         }
  | Expr Add Term      { $$ = $1 + $3;    }
  | Expr Sub Term      { $$ = $1 - $3;    }
  ;
Term  : Fact               { $$ = $1;         }
  | Term Mul Fact      { $$ = $1 * $3;    }
  | Term Div Fact      { if($3==0){ 
                yyerror("Divide by Zero Encountered.");
            break;}
               else
                $$ = $1 / $3;  
                   }
  ;
Fact  : Prim               { $$ = $1;        }
  | '-' Prim           { $$ = -$2;       }
  ;      
Prim  : LP Expr RP         { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
Id    :NUM                 { $$ = yylval;   printf("%d",yylval); }
  ; 
Add   : '+' {printf("+");}
Sub   : '-' {printf("-");}
Mul   : '*' {printf("*");}
Div   : '/' {printf("/");}
LP    : '(' {printf("(");}
RP    : ')' {printf(")");}

%%

void yyerror(char *mesg); /* this one is required by YACC */

main(int argc, char* *argv){
char ch,c;
FILE *f;    
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("%s ", mesg);
}

Thanks EJP & EMACS User for responding.

Nikul Vyas
  • 363
  • 3
  • 7
  • 30