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

Yacc未解析txt文件中的第二个表达式,c,posix,yacc,lex,regexp-grammars,C,Posix,Yacc,Lex,Regexp Grammars,我正在尝试解析.txt文件中的算术表达式集。(每行一个)我能够得到第一行的正确逻辑,但是解析器给出了第二个表达式的0。此外,我想在输出中打印整个字符串,但不知从哪里开始 Lex %{ #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])*

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

Lex

%{
#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  '?'; }

%%
输出

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

=21
Bad Expression : syntax error
4+3-2*(-7)=21
65*+/abc=Bad Expression : syntax error
9/3-2*(-5)=13
即使我从文本文件的第2行int中删除了错误的表达式,解析器也会给出结果

=21 
=0 
而不是

=21    
=13
我尝试在while循环中使用file handling选项读取数据并将其存储在variable&display算术表达式中,并在循环中使用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未解析第二个表达式

9/3-2*(-5)
是的。这就是语法错误的来源。如果它没有解析它,它就不能给出它的语法错误

预期产量

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

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

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

规则

| '-' Expr           { $$ = -$2;       }
应该读

| '-' Fact           { $$ = -$2;       }
最后,您需要做一些关于运算符优先级的事情。我想知道这种奇怪的表达语法是从哪里来的。有很多正确的例子。大概是这样的:

expression
    : term
    | expression '+' term
    | expression '-' term
    ;
term
    : factor
    | term '*' factor
    | term '/' factor
    ;
factor
    : primary
    | '-' primary
    ;
primary
    : ID
    | NUM
    | '(' expression ')'
    ;
错误和遗漏除外

Yacc未解析第二个表达式

9/3-2*(-5)
是的。这就是语法错误的来源。如果它没有解析它,它就不能给出它的语法错误

预期产量

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

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

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

规则

| '-' Expr           { $$ = -$2;       }
应该读

| '-' Fact           { $$ = -$2;       }
最后,您需要做一些关于运算符优先级的事情。我想知道这种奇怪的表达语法是从哪里来的。有很多正确的例子。大概是这样的:

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",$1);} 
  | Calc Expr          {printf(" = %d\n",$2);}
  | Calc error         {yyerror("\n");}
  ;
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 \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);
}
%{
#包括
#包括
#定义YYSTYPE int/*Yacc堆栈的属性类型*/
extern int yylval;/*由lex定义,持有cur令牌的属性*/
extern char yytext[];/*由lex定义并保存最新的标记*/
外部文件*yyin;/*由lex定义;lex从该文件读取*/
%}
%令牌数
%%
计算:Expr{printf(=%d\n“,$1);}
|计算表达式{printf(=%d\n“,$2);}
|计算错误{yyerror(“\n”);}
;
Expr:Term{$$=$1;}
|Expr'+'项{$$=$1+$3;}
|Expr'-'项{$$=$1-$3;}
;
术语:事实{$$=$1;}
|术语“*”事实{$$=$1*$3;}
|术语“/”事实{如果($3==0){
yyerror(“遇到零除”);
中断;}
其他的
$$ = $1 / $3;    
}
;
事实:Prim{$$=$1;}
|“-”Prim{$$=-$2;}
;      
Prim:“('Expr')”{$$=$2;}
|Id{$$=$1;}
;
Id:NUM{$$=yylval;}
;
%%
无效错误(字符*mesg);/*这是YACC所要求的*/
主(内部argc,字符**argv){
char-ch,c;
文件*f;
如果(argc!=2){printf(“useage:calc filename\n”);退出(1);}
如果(!(yyin=fopen(argv[1],“r”){
printf(“无法打开文件”);退出(1);
}
/*  
f=fopen(argv[1],“r”);
如果(f!=NULL){
字符行[1000];
while(fgets(line,sizeof(line),f)!=NULL)
{
fprintf(标准输出,“%s”,行);
yyparse();
}
}
*/
yyparse();
}
无效错误(字符*mesg){
printf(“\n%s”,mesg);
}

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

代码工作得很好,只是需要编辑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",$1);} 
  | Calc Expr          {printf(" = %d\n",$2);}
  | Calc error         {yyerror("\n");}
  ;
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 \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);
}
%{
#包括
#包括
#定义YYSTYPE int/*Yacc堆栈的属性类型*/
extern int yylval;/*由lex定义,持有cur令牌的属性*/
extern char yytext[];/*由lex定义并保存最新的标记*/
外部文件*yyin;/*由lex定义;lex从该文件读取*/
%}
%令牌数
%%
计算:Expr{printf(=%d\n“,$1);}
|计算表达式{printf(=%d\n“,$2);}
|计算错误{yyerror(“\n”);}
;
Expr:Term{$$=$1;}
|Expr'+'项{$$=$1+$3;}
|Expr'-'项{$$=$1-$3;}
;
术语:事实{$$=$1;}
|术语“*”事实{$$=$1*$3;}
|术语“/”事实{如果($3==0){
yyerror(“遇到零除”);
中断;}
其他的
$$ = $1 / $3;    
}
;
事实:Prim{$$=$1;}
|“-”Prim{$$=-$2;}
;      
Prim:“('Expr')”{$$=$2;}
|Id{$$=$1;}
;
Id:NUM{$$=yylval;}
;
%%
无效错误(字符*mesg);/*这是YACC所要求的*/
主(内部argc,字符**argv){
char-ch,c;
文件*f;
如果(argc!=2){printf(“useage:calc filename\n”);退出(1);}
如果(!(yyin=fopen(argv[1],“r”){
printf(“无法打开文件”);退出(1);
}
/*  
f=fopen(argv[1],”