0
votes

I am doing a homework using flex and bison to make a complex number calculator. But my program cannot give a correct output.

.lex file:

%option noyywrap

%{
#include<stdio.h>
#include<stdlib.h>
#include "complex_cal.h"
#define YYSTYPE complex
#include "complex_cal.tab.h"
void RmWs(char* str);
%}

/* Add your Flex definitions here              */
/* Some definitions are already provided to you*/
ws [ \t]+
digits [0-9]
number (0|[1-9]+{digits}*)\.?{digits}*
im [i]
complexnum {ws}*[-]*{ws}*{number}{ws}*[+|-]{ws}*{number}{ws}*{im}{ws}*
op [-+*/()]

%%

{complexnum} {RmWs(yytext); sscanf(yytext,"%lf %lf",&(yylval.real),&(yylval.img));   return CNUMBER;}
{ws} /**/
{op} return *yytext;

%%

/* function provided to student to remove */
/* all the whitespaces from a string.     */

void RmWs(char* str){
int i=0,j=0;
char temp[strlen(str)+1];
strcpy(temp,str);
while (temp[i]!='\0'){
    while (temp[i]==' '){i++;}
    str[j]=temp[i];
    i++; j++;
}
 str[j]='\0';
}

.y file:

%{
#include <stdio.h>
#include <stdlib.h>
#include "complex_cal.h"

/*  prototypes of the provided functions */ 
complex complex_add (complex, complex);
complex complex_sub (complex, complex);
complex complex_mul (complex, complex);
complex complex_div (complex, complex);
/*  prototypes of the provided functions */ 

int yylex(void);
int yyerror(const char*);
%}

%token CNUMBER
%left '+' '-'
%left '*' '/'
%nonassoc '(' ')'


%%
/* start:  Add your grammar rules and actions here */

complexexp: complexexp '+' complexexpmultidiv {$$=complex_add($1, $3);}
        | complexexp '-' complexexpmultidiv {$$=complex_sub($1, $3);}
        | complexexpmultidiv {$$.real=$1.real;$$.img=$1.img;}
        ;

complexexpmultidiv: complexexpmultidiv '*' complexsimple {$$=complex_mul($1, $3);}
                | complexexpmultidiv '/' complexsimple {$$=complex_div($1, $3);}
                | complexsimple {$$.real=$1.real;$$.img=$1.img;}
                ;

complexsimple: '(' complexexp ')' {$$.real=$2.real;$$.img=$2.img;}
            | '(' CNUMBER ')' {$$.real=$2.real;$$.img=$2.img;}
            ;



/* end:  Add your grammar rules and actions here */
%%
int main(){    return yyparse();    }
int yyerror(const char* s){ 
printf("%s\n", s); 
return 0; 
}

/* function provided to do complex addition      */
/* input : complex numbers c1, c2                */
/* output: nothing                               */
/* side effect : none                            */
/* return value: result of addition in c3        */ 
complex complex_add (complex c1, complex c2){
/* c1 + c2 */
complex c3;
c3.real = c1.real + c2.real;
c3.img = c1.img + c2.img;
return c3;
}

/* function provided to do complex subtraction   */
/* input : complex numbers c1, c2                */
/* output: nothing                               */
/* side effect : none                            */
/* return value: result of subtraction in c3     */ 
complex complex_sub (complex c1, complex c2){
/* c1 - c2 */
complex c3;
c3.real = c1.real - c2.real;
c3.img = c1.img - c2.img;
return c3;
}

/* function provided to do complex multiplication */
/* input : complex numbers c1, c2                 */
/* output: nothing                                */
/* side effect : none                             */
/* return value: result of multiplication in c3   */ 
complex complex_mul (complex c1, complex c2){
/* c1 * c2 */
complex c3;
c3.real = c1.real*c2.real - c1.img*c2.img;
c3.img = c1.img*c2.real + c1.real*c2.img;
return c3;
}

/* function provided to do complex division       */
/* input : complex numbers c1, c2                 */
/* output: nothing                                */
/* side effect : none                             */
/* return value: result of c1/c2 in c3            */ 
complex complex_div (complex c1, complex c2){ 
/* c1 / c2 (i.e. c1 divided by c2 ) */
complex c3;
double d;

/*divisor calculation using the conjugate of c2*/
d = c2.real*c2.real + c2.img*c2.img;

c3.real = (c1.real*c2.real + c1.img*c2.img)/d;
c3.img = (c1.img*c2.real - c1.real*c2.img)/d;
return c3;
}

.h file:

#include <string.h>

/* struct for holding a complex number */
typedef struct {
double real;
double img;
} complex;

/* define the return type of FLEX     */
#define YYSTYPE complex

Script for compiling the file:

bison -d -v complex_cal.y
flex -ocomplex_cal.lex.yy.c complex_cal.lex
gcc -o complex_cal complex_cal.lex.yy.c complex_cal.tab.c
./complex_cal

Some correct sample run of the program:

input:(5+6i)*(6+1i)

output:24.000000+41.000000i

input:(7+8i)/(-3-4i)*(5+7i)

output:-11.720000-14.040000i

input:(7+8i)/((-3-4i)*(5+7i))

output:-0.128108+0.211351i

But when I run this program, the program only give an output which is identical to my input. For example, when I input (5+6i)(6+1i), it just gives (5+6i)(6+1i). Even if I input any other things, for example, input "abc" it just gives "abc" and is not syntax error. I don't know where the problem is and I hope to know how to solve it.

3
when you accept an answer that was most helpful to you, you 1. get +2 rep and 2. signal to others that your question got an answer which is satisfactory to you. Later, when you rep is 15 or more, you can upvote those answers which you deem "good".Will Ness

3 Answers

1
votes

The echoing comes from having input that doesn't match any of the lex rules. In general, you want to have a terminal "error" lex rule after all the other lex rules:

.    { fprintf(stderr, "Unexpected input character '%c', ignoring\n", *yytext; }

With that added, you should start seeing messages about unexpected input characters. If those messages seem wrong (eg, it looks to you like those characters should be recognized as part of a complexnum or some other token), then it means your regular expressions for those other tokens are wrong.

To debug your grammar, compile with the flag -DYYDEBUG (add that to the gcc line of your script, before any of the source files), and set the YYDEBUG env var when running your program (enter the command YYDEBUG=1 ./complex_cal.) This will cause your bison-generated parser to print out various messages about the tokens it gets, the states it is shifting to, and the rules it is reducing. By working through those and seeing what unexpected things are happening, you should be able to debug any problems with your grammar.

0
votes

Declare:

complex result;

Add to the top of the rules:

s: complexexep { result = $1; YYACCEPT; }

Into your main() function:

if (yyparse() == 0)
  printf("(%lf, %lf)\n", result.real, result.img);
else
  printf("Error!\n");

And add to the lex file (as last rule):

. { return (yytext[0]); };
0
votes

The output isn't actually repeating everything you put in as input. Instead, it removes all the whitespaces. For example, 'a b c' will output 'abc'.