这是我第一次尝试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}}
如果有人能够解释我的令牌规则如何运作那么那将是很棒的。也许就像我自己能想到的那样。
答案 0 :(得分:1)
规则很简单,Lex正在搜索正则表达式,匹配标记并将它们提供给Yacc。 Yacc正在使用yylex()
函数来实现此目的。
您的问题尚不完整。你有用Yacc文件写的其他东西吗?
Yacc文件由三部分组成:
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就是为了这个。