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
号
这里没有打印输入表达式的内容,因此没有理由这样做。
也没有错误恢复,因此如果存在语法错误,就不可能执行打印
规则
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()。但是计算和语法工作得很好。