关于C#:Yacc没有解析txt文件中的第二个表达式

Yacc not parsing second expression in txt file

我正试图从一个.txt文件中解析一组算术表达式。(每行一个)我可以得到第一行的正确逻辑,但解析器给出的第二个表达式为0。此外,我想在输出中打印整个字符串,但从何处开始会感到困惑。

莱克斯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
%{
#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

]+$
other   .

%%

{ws}    {  /*Nothing*/ }
{digit} {  yylval = atoi(yytext); return NUM;}
{op}    {  return yytext[0];}
{other} {  printf("bad %c bad %d
"
,*yytext,*yytext); return  '?'; }

%%

YACC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
%{
#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
"
,$1);}
  | Calc Expr          {printf(" = %d
"
,$1);}
  ;
Expr  : Expr '+' Expr  { $$ = $1 + $3;    }
  | Expr '-' Expr      { $$ = $1 - $3;    }
  | Expr '*' Expr      { $$ = $1 * $3;    }
  | Expr '/' Expr      { if($3==0)
                          yyerror("Divide by Zero Encountered.");
                         else
                          $$ = $1 / $3;    
                       }
  | '-' Expr           { $$ = -$2;       }
  | Fact               { $$=$1;          }
  ;      
Fact  : '(' Expr ')'   { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
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
"
); exit(1);}
if( !(yyin = fopen(argv[1],"r")) ){
       printf("cannot open file
"
);exit(1);
 }
yyparse();
}

void yyerror(char *mesg){
printf("Bad Expression : %s
"
, mesg);
}

文本文件

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

产量

1
2
=21
Bad Expression : syntax error

预期产量

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

即使我从文本文件的第2行中删除了不正确的表达式,解析器也会给出结果。

1
2
=21
=0

而不是

1
2
=21    
=13

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

使用命令运行代码

1
2
3
4
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会通过移位来解决移位减少冲突,这意味着它会使这些相互递归的规则具有关联性。所以表达式

1
9/3-2*(-5)

被分析为

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

对于整数运算,最后的除法是9/13,即0。


Yacc not parsing second expression

是的。这就是语法错误的来源。如果它不分析它,就不能给出它的语法错误。

Expected output

这里没有打印输入表达式的内容,因此没有理由这样做。

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

Calc : Calc Expr规则应打印$2而不是$1

规则

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

应该读

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

最后,您需要对操作符优先级做些什么。我想知道你是从哪里得到这种奇怪的表达语法的。有很多正确的例子。像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
expression
    : term
    | expression '+' term
    | expression '-' term
    ;
term
    : factor
    | term '*' factor
    | term '/' factor
    ;
factor
    : primary
    | '-' primary
    ;
primary
    : ID
    | NUM
    | '(' expression ')'
    ;

错误和遗漏除外。


代码运行良好,只需要编辑yacc。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
%{
#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
"
,$1);}
  | Calc Expr          {printf(" = %d
"
,$2);}
  | Calc error         {yyerror("
"
);}
  ;
Expr  : Term               { $$ = $1;         }
  | Expr '+' Term      { $$ = $1 + $3;    }
  | Expr '-' Term      { $$ = $1 - $3;    }
  ;
Term  : Fact               { $$ = $1;         }
  | Term '*' Fact      { $$ = $1 * $3;    }
  | Term '/' Fact      { if($3==0){
                yyerror("Divide by Zero Encountered.");
                            break;}
               else
                $$ = $1 / $3;    
                   }
  ;
Fact  : Prim               { $$ = $1;        }
  | '-' Prim           { $$ = -$2;       }
  ;      
Prim  : '(' Expr ')'       { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
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
"
); exit(1);}
if( !(yyin = fopen(argv[1],"r")) ){
       printf("cannot open file
"
);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("
%s"
, mesg);
}

我试图打印表达式,但在while循环中不可能一行一行地读取文件并调用yyparse()。但是计算和语法工作得很好。