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。
我正在尝试从 .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。