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

时间:2017-02-14 01:41:14

标签: 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 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);
}

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%cbad%d\n",*yytext,*yytext); return  '?'; }

%%

我的文本文件包含以下两个表达式:

4+3-2*(-7)
9/3-2*(-5)

我希望输出为:

4+3-2*(-7)=21
9/3-2*(-5)=13

但输出是:

=21
=13

因为解析器会立即执行所有计算,所以这(注释代码)不合法使用。因此,需要将pass输入表达式显示为语法并在Calc块中打印。我无法在谷歌上找到任何与语法显示输入有关的信息。请提前评论和评论。建议。

2 个答案:

答案 0 :(得分:0)

你不想在语法中这样做。太复杂了,太过于受到语法可能做的重新排列的影响。您可以考虑在词法分析器中执行此操作,即在返回之前在除空白操作之外的每个操作中打印yytext,但是我会在读取时通过覆盖 lex来回显所有输入( 1)的输入功能。

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

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

char *

最好写成:

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

这样解析器就会看到它并产生语法错误,因此您不必自己打印任何内容。此技术还允许您删除单个特殊字符{other} { return yytext[0]; } 的规则,因为解析器将通过+,-=*,/,(,)识别它们。

答案 1 :(得分: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);
}

感谢EJP&amp; EMACS用户回复。