0
votes

I have a new problem from the question: Call a function in a Yacc file from another c file So this time, I confront with the problem of yyin function in Lex and Yacc. My codes are following:

calc.l

%{
#include "y.tab.h"  
extern int yylval;
%}

%%
[0-9]+     { yylval=atoi(yytext); return NUMBER;} 
[ \t];                                           
\n         return 0;                              
.          return yytext[0];                      

%%

calc.y

%{
#include <stdio.h>
#include <string.h>
extern FILE* yyin;
%}
%token NAME NUMBER

%%
statement: NAME '=' expression
|      expression {printf("= %d\n",$1);}
    ;
expression: NUMBER '+' NUMBER {$$=$1+$3;}
    |       NUMBER '-' NUMBER {$$=$1-$3;}
    |       NUMBER 'x' NUMBER {$$=$1*$3;}
    |       NUMBER '/' NUMBER
                    {   if($3 == 0)
                            yyerror("Error, cannot divided by zero");
                        else
                            $$=$1/$3;
                    }
    |       NUMBER            {$$=$1;}
;
%%

void parse(FILE* fileInput)
    {
        yyin= fileInput;
        while(feof(yyin)==0)
        {
        yyparse();
        }
    }

main.c

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

int main(int argc,char* argv[])
    {
    FILE* fileInput;
    char inputBuffer[36];
    char lineData[36];

    if((fileInput=fopen(argv[1],"r"))==NULL)
        {
        printf("Error reading files, the program terminates immediately\n");
        exit(0);
        }
    parse(fileInput);
    }

test.txt

2+1
5+1 
1+3

This is how my codes work:

  1. I created main.c to open a file and read it then call a function, parse(), with parameter fileInput.
  2. In calc.y, I set the pointer yyin to be the same as fileInput so the parser can loop and read all lines in a text file (test.txt)

The problem is that yyin didn't read all lines in the text. The result I got is

= 3

The result I should get is

= 3
= 6
= 4

How could I solve this problem. Note that, I want main.c to remain.

2
exit(0) means your program completed successfully. Are you sure you about the exit() call here if((fileInput=fopen(argv[1],"r"))==NULL) { printf("Error reading files, the program terminates immediately\n"); exit(0); } ?Michi

2 Answers

3
votes

This has nothing to do with yyin. Your problem is that your grammar does not recognize a series of statements; it only recognizes one. Having parsed the first line of the file and, ultimately, reduced it to a statement, the parser has nothing more it can do. It has no way to reduce a series of symbols starting with a statement to anything else. Since there is still input left when the parser jams up, it will return an error code to its caller, but the caller ignores that.

To enable the parser to handle multiple statements, you need a rule for that. Presumably you'll want that resulting symbol to be the start symbol, instead of statement. This would be a reasonable rule:

statements: statement
    | statements statement
    ;
2
votes

Your lexical analyzer returns 0 when it reads a newline.

All grammars from Yacc or Bison recognize 0 as meaning EOF (end of file). You told your grammar that you'd reached the end of file; it believed you.

Don't return 0 for newline. You'll probably need to have your first grammar rule iterate (accept a sequence of statements) — as suggested by John Bollinger in another answer.