Yacc 不解析 txt 文件中的第二个表达式

Yacc not parsing second expression in txt file

我正在尝试从 .txt 文件中解析算术表达式集。 (每行一个。)我能够为第一行获得正确的逻辑,但解析器为第二个表达式提供 0。此外,我想在输出中打印整个字符串,但不知道从哪里开始。

莱克斯

%{
#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",);}
  | Calc Expr          {printf(" = %d\n",);}
  ;
Expr  : Expr '+' Expr  { $$ =  + ;    }
  | Expr '-' Expr      { $$ =  - ;    }
  | Expr '*' Expr      { $$ =  * ;    }
  | Expr '/' Expr      { if(==0) 
                          yyerror("Divide by Zero Encountered.");
                         else
                          $$ =  / ;    
                       }
  | '-' Expr           { $$ = -;       }
  | Fact               { $$=;          }
  ;      
Fact  : '(' Expr ')'   { $$ = ;        }
  | Id                 { $$ = ;        }
  ;
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);
}

文本文件

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

输出

=21
Bad Expression : syntax error

预期输出

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

即使我从文本文件的第 2 行中删除错误的表达式,解析器也会给出结果

=21 
=0 

而不是

=21    
=13

我尝试读取数据并将其存储在变量中并显示算术表达式,在 while 循环中使用文件处理选项并在循环中使用 yyparse() 逐行扫描。由于源代码有点复杂,我无法追踪到问题所在,而且我才 20 天就开始研究这个东西。

运行 代码使用命令

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

Yacc not parsing second expression

是的。这就是语法错误的来源。如果它没有解析它,它就不会给出语法错误。

Expected output

这里没有打印输入表达式的东西,所以没有理由有这种期望。

也没有错误恢复,因此如果存在语法错误,则不可能执行输出 = 的缩减。

Calc : Calc Expr 的规则应该打印 </code>,而不是 <code>

规则

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

应该阅读

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

最后,您需要对运算符优先级做一些处理。我想知道你从哪里得到这个奇怪的表达式语法。有很多正确的例子。像这样:

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

错误和遗漏除外。

代码在改进后工作正常,只需要编辑 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",);} 
  | Calc Expr          {printf(" = %d\n",);}
  | Calc error         {yyerror("\n");}
  ;
Expr  : Term               { $$ = ;         }
  | Expr '+' Term      { $$ =  + ;    }
  | Expr '-' Term      { $$ =  - ;    }
  ;
Term  : Fact               { $$ = ;         }
  | Term '*' Fact      { $$ =  * ;    }
  | Term '/' Fact      { if(==0){ 
                yyerror("Divide by Zero Encountered.");
                            break;}
               else
                $$ =  / ;    
                   }
  ;
Fact  : Prim               { $$ = ;        }
  | '-' Prim           { $$ = -;       }
  ;      
Prim  : '(' Expr ')'       { $$ = ;        }
  | Id                 { $$ = ;        }
  ;
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);
 }
/*  
 f=fopen(argv[1],"r");
 if(f!=NULL){
char line[1000];
while(fgets(line,sizeof(line),f)!=NULL)
    {
            fprintf(stdout,"%s",line);
        yyparse();
    }

}
*/
yyparse();
}

void yyerror(char *mesg){
printf("\n%s", mesg);
}

我尝试打印表达式,但逐行读取文件并在 while 循环中调用 yyparse() 是不可能的。但是计算和语法工作正常。

问题是,如果您不使用优先规则指定优先级(或通过重写语法,如其他人所建议的那样),yacc 会通过移位解决 shift-reduce 冲突,这意味着它使此类相互递归规则 right-associative。所以表达式

9/3-2*(-5)

被解析为

9/(3-(2*(-5)))

使用整数运算,最后的除法结果为 9/13,即 0。