我正在使用Flex和Bison开发一个程序。 我的任务可以仅使用Flex(使用开始条件等)完成,但我已经明白使用Bison可能会让我的生活更轻松。 我的任务是设计一个识别编程语言声明部分的程序。 通过下面的代码可以理解它的语法和逻辑。 我的问题是,我希望我的程序能够将代码的每个部分识别为可接受的声明部分,该部分仅以 “ var ”关键字开头! 到现在为止,我还没有成功。 我怎么能成功呢?
我在我的.l(flex)和.y(野牛)文件下面。
exercise4.l
%{ #include %} %% [ tn]+ { /* Ignore all whitespaces */ } ";" { /* Ignore all semicolons */ } ":" { /* Ignore all colons */ } var { printf("A keyword: %sn",yytext); return VAR; } real { printf("A variable type: %sn",yytext); return REAL; } boolean { printf("A variable type: %sn",yytext); return BOOLEAN; } integer { printf("A variable type: %sn",yytext); return INTEGER; } char { printf("A variable type: %sn",yytext); return CHAR; } [a-zA-Z][a-zA-Z0-9_]* { printf("A variable name: %sn",yytext); return VAR_NAME; } . { printf("Unrecognized character!n"); return yytext[0]; } %%
exercise4.y
%{ #include %} %token VAR VAR_NAME REAL BOOLEAN INTEGER CHAR %% program : VAR typedecls ; typedecls : typedecl | typedecls typedecl ; typedecl : varlist ':' var_type ';' ; varlist : VAR_NAME | varlist ',' VAR_NAME ; var_type : REAL | BOOLEAN | INTEGER | CHAR ; %% main( argc, argv ) int argc; char **argv; { extern FILE *yyin; ++argv, --argc; /* skip over program name */ if ( argc > 0 ) yyin = fopen( argv[0], "r" ); else yyin = stdin; //yylex(); yyparse(); } yyerror(char *s) { printf("nErrorn"); } #include "lex.yy.c"
您的扫描仪永远不会返回:
或;
令牌(和抱怨,
未被承认)。 但是你的语法包括那些令牌。
所以,
typedecl : varlist ':' var_type ';' ;
永远无法匹敌。 它没有看到:
它正在期待,因此var_type
是意外的。 (它永远不会匹配;
如果它那么远。)
我不知道你所遵循的是什么古老的教程,但主要的pre-ansi原型表明它是在上个世纪(而不是在最后几年)。 作为一个粗略的指南,我稍微更新了你的文件。
这是exercise4.l; 最重要的修改是我删除了手工构建的跟踪日志,因为我打算使用flex的内置调试function。 我还添加了一些选项来减少编译器警告,并启用行号跟踪以用于错误消息。 我离开了虫子。
/* File: exercise4.l */ %{ /* The bison-generated header file includes token declarations */ #include "exercise4.tab.h" %} %option noinput nounput noyywrap nodefault %option yylineno %% [ tn]+ { /* Ignore all whitespaces */ } ";" { /* Ignore all semicolons. BUG */ } ":" { /* Ignore all colons. BUG */ } var { return VAR; } real { return REAL; } boolean { return BOOLEAN; } integer { return INTEGER; } char { return CHAR; } [a-zA-Z][a-zA-Z0-9_]* { return VAR_NAME; } . { return yytext[0]; }
这里是解析器,有一些修复(比如使用1989 C标准中的标准C原型语法):
/* File: exercise4.y */ %{ /* Used in this file */ #include /* Forward and external declarations */ extern int yylineno; int yylex(); void yyerror(const char* msg); %} /* These two options make error messages more informative */ %define parse.lac full %error-verbose %token VAR VAR_NAME REAL BOOLEAN INTEGER CHAR %% program : VAR typedecls typedecls : typedecl | typedecls typedecl typedecl : varlist ':' var_type ';' varlist : VAR_NAME | varlist ',' VAR_NAME ; var_type : REAL | BOOLEAN | INTEGER | CHAR ; %% /* Welcome to 1990 */ int main( int argc, char** argv ) { extern FILE *yyin; if ( argc > 1 ) yyin = fopen( argv[1], "r" ); else yyin = stdin; if (!yyin) { /* If you don't check, you'll end up segfaulting when * yylex tries to read from NULL. Checking lets us print * a hopefully meaningful error message. */ perror("Could not open file for reading"); return 1; } return yyparse(); } /* Now that error messages have some content, it's worthwhile * actually using the argument passed to yyerror */ void yyerror(const char* msg) { fprintf(stderr, "At line %d: %sn", yylineno, msg); }
现在,我按顺序通过flex,bison和gcc运行文件,以生成可执行文件:
# The `-d` option to flex causes it to insert debugging traces. That's # a lot less effort and a lot more useful than rolling your own trace # logs. flex -d -o exercise4.scan.c exercise4.l # The `-d` option to bison causes it to output a header file, whose name # is the same as the output file name with `.c` changed to `.h`. That's # the file which we need to `#include` in the scanner, so that token # names are available to scanner actions. Bison also has a debugging # feature, but you need to use `-t` to enable it, plus add a line at # runtime. For now, we'll leave it out. bison -d -o exercise4.tab.c exercise4.y # Now compile and link an executable: gcc -Wall -g -o exercise4 exercise4.tab.c exercise4.scan.c
通常,三个shell命令将进入Makefile,因此您只需键入make exercise4
即可创建可执行文件。 但那里没有什么真正复杂的。
现在,我们可以尝试一下。 由于我没有修复错误,你很容易看到问题所在:
var a, b: integer; --accepting rule at line 14 ("var") --accepting rule at line 11 (" ") --accepting rule at line 19 ("a") --accepting rule at line 20 (",") --accepting rule at line 11 (" ") --accepting rule at line 19 ("b") --accepting rule at line 13 (":") --accepting rule at line 11 (" ") --accepting rule at line 17 ("integer") At line 1: syntax error, unexpected INTEGER, expecting ':' or ','
线条开始--
是flex的痕迹。 您可以在识别时看到每个令牌。 因此,当在输入中遇到:
时,执行第13行的规则。 该规则是{ /* Ignore all colons */ }
。 这就是发生的事情。
最后的错误消息由yyerror
打印。 感谢%errors-verbose
指令,它告诉我们它找到了什么( INTEGER
)以及它所期待的内容。
希望一切都有所帮助。
以上就是c/c++开发分享Flex和Bison:使用特定关键字开始一个句子相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/519745.html