Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在YACC语法中回显输入文本?_C_Yacc_File Handling_Regexp Grammars - Fatal编程技术网

如何在YACC语法中回显输入文本?

如何在YACC语法中回显输入文本?,c,yacc,file-handling,regexp-grammars,C,Yacc,File Handling,Regexp Grammars,我试图显示文本文件中的整个算术表达式及其结果,我尝试使用文件处理选项,但它不起作用 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

我试图显示文本文件中的整个算术表达式及其结果,我尝试使用文件处理选项,但它不起作用

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);
}
我希望输出为:

4+3-2*(-7)=21
9/3-2*(-5)=13
但结果是:

=21
=13

因为解析器将一次完成所有计算,所以这(注释代码)是不合法的。所以需要的是将输入表达式传递给语法并在Calc块中打印。我在谷歌上找不到任何关于在语法中显示输入的相关信息。提前感谢您的评论和建议。

您不想在语法中这样做。太复杂了,太容易被语法的任何重新安排所影响。您可以考虑在LeXER中,即在空白动作以外的每一个动作中打印“代码<代码> yyTest<代码> >,但我会通过读取LeX(1)的输入函数来回覆所有输入,

注意:您应该使用flex(1),而不是lex(1),并且请注意,如果您更改,
yyyext
将不再是
char[]
而成为
char*

我在你之前的问题中没有提到,但这条规则:

{other} {  printf("bad%cbad%d\n",*yytext,*yytext); return  '?'; }
最好写为:

{other} {  return yytext[0]; }
这样,解析器将看到它并产生语法错误,因此您不必自己打印任何内容。这项技术还可以让您摆脱单个特殊字符的规则
+,-=*,/,(,)
,因为解析器将通过
yytext[0]
识别它们。最后,我得到了:

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);}
  | error              {yyerror("Bad Expression\n");}
  ;

Expr  : Term               { $$ = $1;         }
  | Expr Add Term      { $$ = $1 + $3;    }
  | Expr Sub Term      { $$ = $1 - $3;    }
  ;
Term  : Fact               { $$ = $1;         }
  | Term Mul Fact      { $$ = $1 * $3;    }
  | Term Div Fact      { if($3==0){ 
                yyerror("Divide by Zero Encountered.");
            break;}
               else
                $$ = $1 / $3;  
                   }
  ;
Fact  : Prim               { $$ = $1;        }
  | '-' Prim           { $$ = -$2;       }
  ;      
Prim  : LP Expr RP         { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
Id    :NUM                 { $$ = yylval;   printf("%d",yylval); }
  ; 
Add   : '+' {printf("+");}
Sub   : '-' {printf("-");}
Mul   : '*' {printf("*");}
Div   : '/' {printf("/");}
LP    : '(' {printf("(");}
RP    : ')' {printf(")");}

%%

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("%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;}
|术语Div事实{if($3==0){
yyerror(“遇到零除”);
中断;}
其他的
$$ = $1 / $3;  
}
;
事实:Prim{$$=$1;}
|“-”Prim{$$=-$2;}
;      
Prim:LP Expr RP{$$=$2;}
|Id{$$=$1;}
;
Id:NUM{$$=yylval;printf(“%d”,yylval);}
; 
添加:'+'{printf(“+”);}
子:'-'{printf(“-”);}
Mul:'*'{printf(“*”);}
Div:'/'{printf(“/”);}
LP:'('{printf(“”;}
RP:'){printf(“)”;}
%%
无效错误(字符*mesg);/*这是YACC所要求的*/
主(内部argc,字符**argv){
char-ch,c;
文件*f;
如果(argc!=2){printf(“useage:calc filename\n”);退出(1);}
如果(!(yyin=fopen(argv[1],“r”){
printf(“无法打开文件”);退出(1);
}
yyparse();
}
无效错误(字符*mesg){
printf(“%s”,mesg);
}

感谢EJP&EMACS用户的响应。

您不会说它以何种方式不起作用。给我们一个线索。我想要一个像9/3-2*(-5)=13这样的输出,但只有当语法将获取输出时才有可能。仍然没有帮助。你说你在谷歌上找不到任何相关信息。你认为什么是相关的?你在找什么?使用详细信息更新您的问题,而不是在此处进行注释。我已经更新了Emacs。我没有解决方案,但有一个建议:为什么不为*f的每一行保留一个数组变量,然后在返回yytext{0}时,在返回前追加该行。在循环中执行此操作,以便可以跳过具有错误条件的行。
{other} {  return yytext[0]; }
%{
#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);}
  | error              {yyerror("Bad Expression\n");}
  ;

Expr  : Term               { $$ = $1;         }
  | Expr Add Term      { $$ = $1 + $3;    }
  | Expr Sub Term      { $$ = $1 - $3;    }
  ;
Term  : Fact               { $$ = $1;         }
  | Term Mul Fact      { $$ = $1 * $3;    }
  | Term Div Fact      { if($3==0){ 
                yyerror("Divide by Zero Encountered.");
            break;}
               else
                $$ = $1 / $3;  
                   }
  ;
Fact  : Prim               { $$ = $1;        }
  | '-' Prim           { $$ = -$2;       }
  ;      
Prim  : LP Expr RP         { $$ = $2;        }
  | Id                 { $$ = $1;        }
  ;
Id    :NUM                 { $$ = yylval;   printf("%d",yylval); }
  ; 
Add   : '+' {printf("+");}
Sub   : '-' {printf("-");}
Mul   : '*' {printf("*");}
Div   : '/' {printf("/");}
LP    : '(' {printf("(");}
RP    : ')' {printf(")");}

%%

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("%s ", mesg);
}