cposixyacclexregexp-grammars

Yacc not parsing second expression in txt file


I am trying to parse the set of arithmetic expressions from a .txt file. (one in each line.) I am able to get the proper logic for first line but the parser gives 0 for second expression. Moreover, I want to print the whole string in the output but getting confused from where to start.

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 %c bad %d \n",*yytext,*yytext); return  '?'; }

%%

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",$1);}
  ;
Expr  : Expr '+' Expr  { $$ = $1 + $3;    }
  | Expr '-' Expr      { $$ = $1 - $3;    }
  | Expr '*' Expr      { $$ = $1 * $3;    }
  | Expr '/' Expr      { if($3==0) 
                          yyerror("Divide by Zero Encountered.");
                         else
                          $$ = $1 / $3;    
                       }
  | '-' Expr           { $$ = -$2;       }
  | Fact               { $$=$1;          }
  ;      
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,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("Bad Expression : %s\n", mesg);
}

Text File

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

Output

=21
Bad Expression : syntax error

Expected Output

4+3-2*(-7)=21
65*+/abc=Bad Expression : syntax error
9/3-2*(-5)=13

Even if I remove the bad expression from 2nd line int the text file the parser is giving result

=21 
=0 

instead of

=21    
=13

I tried to read data and store it in variable & display arithmetic expression using file handling option in while loop and using yyparse() in the loop to scan line by line. I am not able to track down the problem as the source code is bit complex and I have started studying this thing from just 20 days.

Running Code By using Commands

yacc -v -t -d calc.yacc (I am getting 22 shift/reduce conflicts.)
lex calc.lex
gcc y.tab.c lex.yy.c -lm -ll -o calc
./calc calc.txt

Solution

  • Yacc not parsing second expression

    Yes it is. That's where the syntax error comes from. If it wasn't parsing it, it couldn't give a syntax error for it.

    Expected output

    There is nothing here that prints the input expression, so there is no reason for this expectation.

    There is also no error recovery, so no possibility of performing the reduction that prints = if there is a syntax error.

    The rule for Calc : Calc Expr should print $2, not $1.

    The rule

    | '-' Expr           { $$ = -$2;       }
    

    should read

    | '-' Fact           { $$ = -$2;       }
    

    And finally you need to do something about operator precedence. I'm wondering where you got this bizarre expression grammar from. There are plenty of correct examples. Something like this:

    expression
        : term
        | expression '+' term
        | expression '-' term
        ;
    term
        : factor
        | term '*' factor
        | term '/' factor
        ;
    factor
        : primary
        | '-' primary
        ;
    primary
        : ID
        | NUM
        | '(' expression ')'
        ;
    

    Errors and omissions excepted.