我开始了整个Flex和Bison的世界。 所以我按照教程为flex编写了这个l文件:
%{ #include #include void yyerror(char *); #include "y.tab.h" %} %% /******************** RULES ********************/ /* One letter variables */ [az] { yylval = *yytext - 'a'; // This is to return a number between 0 and 26 representting the letter variable. printf("VAR: %sn",yytext); return VARIABLE; } /* Integer constants */ [0-9]+ { yylval = atoi(yytext); printf("INT: %dn",yylval); return INTEGER; } /* Operators */ [-+()=/*n]+ { printf("OPR: %sn",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: %dn", $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("%sn",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: %dn", $1); } ^ bas.y: In function 'yyerror': bas.y:39:4: warning: incompatible implicit declaration of built-in function 'printf' printf("%sn",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的代码中自动生成的。 可以改成更有意义的东西吗? 我是正确的假设语法错误是因为程序找到了)和换行符和变量,并且这不符合程序语句,如语法所定义的那样?
我已经清楚地包含了用于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
你应该做的是在你的bas.y
文件中添加一个prolog块,包括#include
。
[-+()=/*n]+ {... return *yytext; ...}
此弹性模式匹配集[-+()=/*n]
中的任意数量的字符。 所以在输入x=(3+5)n
, )n
被匹配为单个标记 。 但是,该操作返回*yytext
, *yytext
的第一个字符,实际上忽略了n
。 由于你的语法需要n
,这会产生语法错误。
只需从模式中删除重复运算符即可。
可以将错误消息更改为更有意义的内容吗?
如果您有一个相当现代的野牛,请添加声明
%error-verbose
到你的野牛文件的开头。
以上就是c/c++开发分享来自词法分析器和语法的简单计算器的意外行为相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/519340.html