BISON和YACC - 如何输入完整的声明

时间:2016-01-26 16:53:29

标签: bison yacc lex

这是我第一次尝试BISON,而我却试图弄清楚如何采用完整的声明,例如%token ASSIGNMENT %token <intToken> INTNUMBER %token <intToken> INTTOKEN %type <statement> STATEMENT STATEMENT: '\n' | INTTOKEN STATEMENT {printf("Token");} | INTNUMBER STATEMENT {printf("Number");} | STATEMENT ASSIGNMENT STATEMENT{printf("Assinging");} | INTTOKEN '\t' ASSIGNMENT '\t' INTNUMBER STATEMENT {printf("FULL STATEMENT COMPLETE");} |error {yyerror("ERROR");} 。每当我尝试这样做时,我都没有得到任何输出。但如果我分别尝试每个部分,那么我会得到每个部分的输出。我的代码如下,当然只是其中的一部分:

.y文件

"="                                 return ASSIGNMENT;
[0-9]+                      { ECHO; yylval.integer = atoi(yytext); return INTNUMBER; }
[a-fA-F]+[a-zA-Z]+      { ECHO; yylval.variableInteger = yytext; return INTTOKEN; }

我的.l文件:

{{1}}

如果有人能够解释我的令牌规则如何运作那么那将是很棒的。也许就像我自己能想到的那样。

1 个答案:

答案 0 :(得分:1)

规则很简单,Lex正在搜索正则表达式,匹配标记并将它们提供给Yacc。 Yacc正在使用yylex()函数来实现此目的。

您的问题尚不完整。你有用Yacc文件写的其他东西吗?

Yacc文件由三部分组成:

  • 后来位于y.tab.c文件(Yacc生成)开头附近的C代码,在此部分文件中需要声明extern int yylex(void)函数。 Yacc实际上需要两件事情,第一件事是yylex(),第二件是yyerror()
  • 第二部分是带有规则和行为的语法

  • 第三部分是调用yyparse()的主要功能。

对于令牌和类型的声明,可以在文件的%{ %}部分之前或之后完成。一些基本的Yacc代码如下所示:

%{ 
 #include <stdio.h>
 #include ...

 /* Extern keyword is just good practice, it doesn't have to be written */
 extern int yylex(void);

 void yyerror(char *string){

   fprintf(stderr,"Syntax error: %s", string);
   exit(EXIT_FAILURE);
 }

%}

%%
  /* Grammar with actions */
%%

int main(){

  yyparse();
  return 0;
}

那么这是如何工作的? Yacc正在使用yylex()函数来获取令牌,然后使用他的语法来确定其他所有内容。为了实现这一点,您必须将使用flex生成的lex.yy.c和使用yacc生成的y.tab.c编译为目标文件,然后将这两个目标文件编译为一个可执行文件。

例如:

yacc program.y
flex program.lex
gcc -c y.tab.c -o y.tab.o
gcc -c lex.yy.c -o lex.yy.o
gcc y.tab.o lex.yy.o -o program

注意:如果您在Yacc文件中声明令牌,则需要在使用y.tab.h运行Yacc命令时生成yacc -d program.y文件,然后再包括这个文件在你的Lex中。选项-d就是为了这个。