我开始研究Flex和Bison的整个世界。所以我按照教程为flex写了这个l文件:
%{
#include <stdio.h>
#include <stdlib.h>
void yyerror(char *);
#include "y.tab.h"
%}
%%
/******************** RULES ********************/
/* One letter variables */
[a-z] {
yylval = *yytext - 'a'; // This is to return a number between 0 and 26 representting the letter variable.
printf("VAR: %s\n",yytext);
return VARIABLE;
}
/* Integer constants */
[0-9]+ {
yylval = atoi(yytext);
printf("INT: %d\n",yylval);
return INTEGER;
}
/* Operators */
[-+()=/*\n]+ { printf("OPR: %s\n",yytext); return *yytext; /*\n is considered an operator because it signals the end of a statement*/ }
/* This skips white space and tab chararcters */
[ \t] ;
/* Anything esle is not allowed */
. yyerror("Invalid character found");
/***************** SUBROUTINES *****************/
%%
int yywrap(void){
return 1;
}
这就是语法:
/***************** DEFINITIONS *****************/
%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'
%{
void yyerror(char *);
int yylex(void);
int sym[26];
%}
%%
/******************** RULES ********************/
program:
program statement '\n'
|
;
statement:
expr { printf("EXPR: %d\n", $1); }
| VARIABLE '=' expr { sym[$1] = $3; }
;
expr:
INTEGER
| VARIABLE { $$ = sym[$1]; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| '(' expr ')' { $$ = $2; }
;
%%
/***************** SUBROUTINES *****************/
void yyerror(char *s){
printf("%s\n",s);
}
int main(void) {
yyparse();
return 0;
}
出现了几个问题。第一个来自编译时。这是我编译的方式:
bison -d bas.y -o y.tab.c
flex bas.l
gcc y.tab.h lex.yy.c y.tab.c -o bas_fe
这给了我两个这样的警告:
bas.y:24:7: warning: incompatible implicit declaration of built-in function ‘printf’
expr { printf("EXPR: %d\n", $1); }
^
bas.y: In function ‘yyerror’:
bas.y:39:4: warning: incompatible implicit declaration of built-in function ‘printf’
printf("%s\n",s);
现在,它们是警告和打印工作,但我发现它很奇怪,因为我已经清楚地包含了使用printf函数的库。
我真正的问题来自于我与该计划的互动。这是控制台输出:
x = (3+5)
VAR: x
OPR: =
OPR: (
INT: 3
OPR: +
INT: 5
x
OPR: )
VAR: x
syntax error
由此产生了几个问题。 1)输入x =(3 + 5)后,程序打印输出不包括')'为什么?
2)当输入x(预期输出为8)时,才会出现')'。为什么?
3)然后出现“语法错误”消息。我假设消息是在y.tab.c的代码中自动生成的。可以改成更有意义的东西吗?我是正确的,假设语法错误是因为程序找到了)和换行符和变量,并且这不符合程序语句,如语法所定义的那样?
答案 0 :(得分:0)
我已清楚地包含了使用printf函数的库。
您在Flex文件中包含了
stdio.h
,但在您的bison文件中没有。关于printf
未声明的警告来自你的野牛文件,而不是你的flex文件。
使用gcc(或任何其他C编译器)编译多个文件时,文件将独立编译,然后链接在一起。所以你的命令
gcc y.tab.h lex.yy.c y.tab.c -o bas_fe
不会连接这三个文件并将它们编译为一个单元。相反,它独立编译三个文件,包括无用地编译头文件y.tab.h
。
您应该做的是在您的#include <stdio.h>
文件中添加包含bas.y
的序言块。
[-+()=/*\n]+ {... return *yytext; ...}
此弹性模式匹配集合[-+()=/*\n]
中任意数量的字符。因此,在输入x=(3+5)\n
中,)\n
被匹配为单个令牌。但是,该操作会返回*yytext
yytext
的第一个字符,有效地忽略\n
。由于您的语法需要\n
,因此会产生语法错误。
只需从模式中删除重复运算符即可。
如果您有一个相当现代的野牛,请添加声明
%error-verbose
到你的野牛文件的开头。