0

Now here is my lex code

%{
#include <stdio.h>
#include "y.tab.h"
extern int yylval;
int yywrap();
%}

%%
[a-zA-Z]    {yylval = *yytext; return ALPHABET;}
[0-9]+      {yylval = atoi(yytext); return NUMBER;}
[0-9]+"."[0-9]* {yylval = atof(yytext); return NUMBER;}
"=="        return EQ;
"<="        return LE;
">="        return GE;
"!="        return NE;
[\t]    ;
\n  return 0;
.   return  yytext[0];
%%

int yywrap()
{
    return 1;
}

and here is my yacc code

%{
#include<stdio.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
int flag = 0;
%}

%token NUMBER
%token ALPHABET
%left '+''-' 
%left '*''/''%'
%left '&''|''^''~'
%right EQ LE GE NE'<''>'
%left '('')'
%left UMINUS
%left UPLUS
%start check

%%
check   : E { }
  E:E '+' E {$$ = $1 + $3;}
  |E '-' E  {$$ = $1 - $3;}
  |E '&' E  {$$ = $1 & $3;}
  |E '|' E  {$$ = $1 | $3;}
  |E '^' E  {$$ = $1 ^ $3;}
  |'~' E    {$$ = ~$2;}
  |E EQ E   {$$ = (EQ, $1, $3);}
  |E LE E   {$$ = (LE, $1, $3);}
  |E GE E   {$$ = (GE, $1, $3);}
  |E NE E   {$$ = (NE, $1, $3);}
  |E '<' E  {$$ = ('<', $1, $3);}
  |E '>' E  {$$ = ('>', $1, $3);}
  |'(' E ')'    {$$ = $2;}
  |'-' E %prec  UMINUS
            {$$ = - $2;}
  |'+' E %prec  UPLUS
    {$$ = + $2;} 
  |NUMBER   {$$ = $1;}
  |ALPHABET {$$ = $1;}
  ;
%%

int main(int argc, char** argv)
{
    char filename[30];
    char line[300];
    printf("\nEnter filename\n");
    scanf("%s",filename);
    yyin = fopen(filename, "r");
    if(NULL == yyin)
    {
        fprintf(stderr,"Can't read file %s\n",filename);
        return 1;
    }
    else
    {
        while(fgets(line, sizeof line, yyin) != NULL)
        {
            printf("%s\n", line);

        }
        yyparse();  
        fclose(yyin);
        printf("\nValue of yyparse : %d\n",yyparse());
    }
    if(flag == 0)
        printf("\nBoolean Arithmetic Expression is valid\n");

    return 0;
}

void yyerror()
{
    printf("\nBoolean Arithmetic expression is invalid\n\n");
    flag = 1;
}

This is my main part for reading text file and do some operations, so anyone can tell me this how to read multiple line in text file using Yacc. Now I put my fully Yacc code and I try to check Boolean expression is correct or not my text file expressions are : -

a-b
a+b&c
(P!=F+E-O+F-(U>Y+I<N))
(((a+B)-7+4-(c-d))+((P^q)-(L|z))+(m&n)+(O-g)
((A-2)&(B+2)|(C-4)^(D+4)+(~E))==F+(G!=)-(i<j)-(K>M)
((((a+b)-(c+d))-((E-F)+(G-H)))+((a&B)+(c|d))-((e^f)+(~g)+(i==2)-(j!=2)+(k<=8)-(l>=17.98)+(M<N)-(O>p)-((-2+4)+(6-(-5)))))

So my code check only first expression. So my problem is that how to check all expressions line by line.

Now please check where is the problem for reading text line by line and give message expression is valid or not please help. Some expressions are valid and some are invalid so please check and tell me the problem and how to correct it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
s.zen
  • 11
  • 6
  • What do you mean "read multiple line"? If the grammar is set up correctly then the parser should "read multiple lines" automatically. Can you please edit the question to include the grammar (complete if it's small, otherwise an outline)? – Some programmer dude Dec 30 '15 at 05:00

2 Answers2

1

You grammar only handles a single ArithmeticExpression, and once that is done the parser returns.

One way to solve your problem is to modify the parser grammar just a little, so it handles multiple "lines" (or rather multiple expressions in your case) itself:

    ArithmeticExpression_list
      : ArithmeticExpression
      | ArithmeticExpression_list ArithmeticExpression
      ;

Then you simply use the return value of the yyparse() function to see if parsing was successful or not. If yyparse() return 0 then all expressions were syntactically okay.

If you want to print for each and every expression, just add a semantic action for the ArithmeticExpression, if there's a syntax error it will not be invoked.

user207421
  • 305,947
  • 44
  • 307
  • 483
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    Perhaps you meant the second production to be left-recursive, so that the list is produced incrementally rather than piling up on the stack until the entire input is read. Of course, aside from parser stack usage, it makes little difference if the only goal is to validate syntax. – rici Dec 30 '15 at 06:10
  • ** Sir I am not understand what you want to say can you give me example using my code ** – s.zen Dec 30 '15 at 06:17
  • hello sir i am not understand how to do this pleas give me one example please. only that part you initialize it above. – s.zen Dec 31 '15 at 10:07
  • @s.zen *What* part of my answer don't you understand? Just put the rule I show first in the rules-section of your Yacc-file. – Some programmer dude Dec 31 '15 at 11:29
  • %{ #include #include "y.tab.h" extern int yylval; int yywrap(); %} %% [a-zA-Z] {yylval = *yytext; return ALPHABET;} [0-9]+ {yylval = atoi(yytext); return NUMBER;} [0-9]+"."[0-9]* {yylval = atof(yytext); return NUMBER;} "==" return EQ; "<=" return LE; ">=" return GE; "!=" return NE; [\t] ; \n return 0; . return yytext[0]; %% int yywrap() { return 1; } – s.zen Jan 04 '16 at 06:46
  • @s.zen: Please don't try posting code in a comment — it isn't readable, and as the OP, you can edit the question to add the new/extra code. Remember not to destroy the question — add the new code, rather than replacing what was already there, please. (If you're not the OP, it can be necessary to post code in a comment, but then enclose it in back-ticks: ``%{ … %}`` is created from `` `%{ … }%` `` – Jonathan Leffler Jan 04 '16 at 07:05
  • @JonathanLeffler ok sir i can understand but can you give me solution of my problem i put my code , so please check how to read multiple line text by using lex and yacc and checking expression is valid or invalid line by line. – s.zen Jan 04 '16 at 07:20
0

The structure of main() is wrong. It reads the whole of the input file using fgets(), and then seems to expect yyparse() to read some more information from it.

What you probably need to do is:

while (yyparse() == 0)
    printf("OK\n");

Well, something along those lines. You might need to analyze flag, and/or set flag to 0 (or 1) after each iteration. If you want to read lines and have the grammar read the string, you have more work to do — setting up appropriate input functions, etc.

To get the code to compile cleanly, I used the following code. I added #define YY_NO_INPUT and full prototypes and various other changes — and cleaned up the triple comma expressions in the grammar for the comparison operations. They probably aren't what you'll use in the long term, but they satisfy the stringent compiler options I use.

testlex.l

%{
#include <stdio.h>
#include "y.tab.h"
#define YY_NO_INPUT
extern int yylval;
int yywrap(void);
extern void use_yyunput(char c);
%}

%%
[a-zA-Z]    {yylval = *yytext; return ALPHABET;}
[0-9]+      {yylval = atoi(yytext); return NUMBER;}
[0-9]+"."[0-9]* {yylval = atof(yytext); return NUMBER;}
"=="        return EQ;
"<="        return LE;
">="        return GE;
"!="        return NE;
[\t]    ;
\n  return 0;
.   return  yytext[0];
%%

int yywrap(void)
{
    return 1;
}
void use_yyunput(char c)
{
    unput(c);
}

testyacc.y

%{
#include <stdio.h>
#include <assert.h>
extern int yylex(void);
extern int yyparse(void);
extern void yyerror(char *str);
extern FILE* yyin;
int flag = 0;
%}

%token NUMBER
%token ALPHABET
%left '+''-' 
%left '*''/''%'
%left '&''|''^''~'
%right EQ LE GE NE'<''>'
%left '('')'
%left UMINUS
%left UPLUS
%start check

%%
check   : E { }
  E:E '+' E {$$ = $1 + $3;}
  |E '-' E  {$$ = $1 - $3;}
  |E '&' E  {$$ = $1 & $3;}
  |E '|' E  {$$ = $1 | $3;}
  |E '^' E  {$$ = $1 ^ $3;}
  |'~' E    {$$ = ~$2;}
  |E EQ E   {$$ = ($1 == $3);}
  |E LE E   {$$ = ($1 <= $3);}
  |E GE E   {$$ = ($1 >= $3);}
  |E NE E   {$$ = ($1 != $3);}
  |E '<' E  {$$ = ($1 <  $3);}
  |E '>' E  {$$ = ($1 >  $3);}
  |'(' E ')'    {$$ = $2;}
  |'-' E %prec  UMINUS
            {$$ = - $2;}
  |'+' E %prec  UPLUS
    {$$ = + $2;} 
  |NUMBER   {$$ = $1;}
  |ALPHABET {$$ = $1;}
  ;
%%

int main(void)
{
    char filename[30];
    printf("\nEnter filename\n");
    scanf("%s",filename);
    yyin = fopen(filename, "r");
    if(NULL == yyin)
    {
        fprintf(stderr,"Can't read file %s\n",filename);
        return 1;
    }
    else
    {
        while (yyparse() == 0)
        {
            printf("OK\n");
        }
        fclose(yyin);
    }

    if(flag == 0)
        printf("\nBoolean Arithmetic Expression is valid\n");

    return 0;
}

void yyerror(char *str)
{
    assert(str != 0);
    printf("\nBoolean Arithmetic expression is invalid\n\n");
    flag = 1;
}

Compilation and run

The file data contained the data from the question. rmk is a variation on the theme of make.

$ rmk testyacc.o testlex.o
    yacc  testyacc.y
    gcc -O3   -g   -I/Users/jleffler/inc   -std=c11   -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror    -c y.tab.c
    mv y.tab.o testyacc.o
    rm -f y.tab.c
    lex  testlex.l
    gcc -O3   -g   -I/Users/jleffler/inc   -std=c11   -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror    -c lex.yy.c
    mv lex.yy.o testlex.o
    rm -f lex.yy.c
$ gcc -o testit testyacc.o testlex.o
$ ./testit

Enter filename
data
OK
OK
OK

Boolean Arithmetic expression is invalid

$

Your stack uses integers, I believe. The use of atof() isn't going to help very much. That mainly means you've still got a lot of work to do.

Testing on Mac OS X 10.11.2 with GCC 5.3.0 (with flex 2.5.35 Apple(flex-31) and bison (GNU Bison) 2.3 masquerading as lex and yacc).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278