如何在YACC语法中回显输入文本?
我试图显示文本文件中的整个算术表达式及其结果,我尝试使用文件处理选项,但它不起作用 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
%{
#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);
}