0

我正在使用 flex 和 bison 做一个复数计算器的作业。但是我的程序无法给出正确的输出。

.lex 文件:

%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 文件:

%{
#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 文件:

#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

编译文件的脚本:

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

该程序的一些正确示例运行:

输入:(5+6i)*(6+1i)

输出:24.000000+41.000000i

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

输出:-11.720000-14.040000i

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

输出:-0.128108+0.211351i

但是当我运行这个程序时,程序只给出与我的输入相同的输出。例如,当我输入 (5+6i) (6+1i) 时,它只给出 (5+6i) (6+1i)。即使我输入任何其他内容,例如输入“abc”,它也只会给出“abc”,而不是语法错误。我不知道问题出在哪里,我希望知道如何解决它。

4

3 回答 3

1

回显来自与任何 lex 规则不匹配的输入。通常,您希望在所有其他 lex 规则之后有一个终端“错误”lex 规则:

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

添加后,您应该开始看到有关意外输入字符的消息。如果这些消息看起来是错误的(例如,在您看来这些字符应该被识别为复数或其他标记的一部分),那么这意味着您对这些其他标记的正则表达式是错误的。

要调试语法,请使用标志编译-DYYDEBUG(将其添加到gcc脚本行,在任何源文件之前),并YYDEBUG在运行程序时设置 env var(输入命令YYDEBUG=1 ./complex_cal。)这将导致您的野牛生成解析器打印出关于它获得的令牌、它正在转移到的状态以及它正在减少的规则的各种消息。通过解决这些问题并查看正在发生的意外情况,您应该能够调试语法的任何问题。

于 2013-11-11T19:53:25.460 回答
0

输出实际上并没有重复您作为输入输入的所有内容。相反,它会删除所有空格。例如,“ab c”将输出“abc”。

于 2013-11-11T18:05:23.480 回答
0

宣布:

complex result;

添加到规则的顶部:

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

进入你的 main() 函数:

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

并添加到 lex 文件中(作为最后一条规则):

. { return (yytext[0]); };
于 2013-11-10T10:43:28.507 回答