本文共 4330 字,大约阅读时间需要 14 分钟。
导读:关于yacc 和 lex 和在下面链接的文章里已经有所介绍了链接中的文章还介绍了在linux下如何使用yacc和lex工具,下面主要是介绍yacc和lex在windows下的用法。 以下内容属作者为xiaolin,请尊重作者的辛勤劳动,请勿转载。yacc和lex在windows已经移植成功,其中常用的一个工具就是Parser Generator。这个工具使用yacc和lex能够生成Visual C++,Borland C++,Other C/C++以及相关Java代码。下面介绍一下这个工具是如何生成代码并使用Visual C++编译的。注:关于Parser Generator的使用和配置,其实在Parser Generator Help中已经有很详细的介绍,感兴趣的朋友可以去那里查到更多有用的信息。首先要去http://www.bumblebeesoftware.com/downloads.htm下载Parser Generator。安装完毕后,我们可以在它的安装目录下找到一些例子以及编译程序所需的库文件和源文件,这些文件在编译是很重要。单独yacc文件的编译。以下是一个单独的yacc文件,实现一个简单的计算器功能。%{ /************************************************************www.linmu100.com************************************************************/#include #include #define YYSTYPE double /* double type for YACC stack */ %} %token NUMBER %% lines : lines expr '/n' { printf("%g/n", $2); } | lines '/n' | /* e */ | error '/n' { yyerror("reenter last line:"); yyerrok(); } ; expr : expr '+' term { $$ = $1 + $3; } | expr '-' term { $$ = $1 - $3; } | term ; term : term '*' factor { $$ = $1 * $3; } | term '/' factor { $$ = $1 / $3; } | factor ; factor : '(' expr ')' { $$ = $2; } | '(' expr error { $$ = $2; yyerror("missing ')'"); yyerrok(); } | '-' factor { $$ = -$2; } | NUMBER ; %% int main(void) { return yyparse(); } int yylex(void) { int c; while ((c = getchar()) == ' '); if (c == '.' || isdigit(c)) { ungetc(c, stdin); scanf("%lf", &yylval); return NUMBER; } return c; } 我们用Parser Generator的Project --> Parser Wizard创建一个工程,如下图所示,注意红圈部分的设置: 然后设置文件,模板: 其余按默认完成即可: 这时,我们可以看到Parser Generator帮我们自动生成了一个myparser.y文件,语法规则就可以在这里加了。 现在我们把开头展示的yacc源码完全覆盖myparser.y文件,然后编译,成功后会生成三个文件:myparser.c,myparser.h,myparser.v好,现在我们要做的就是用vc来编译myparser.c,myparser.h这两个文件了。打开Microsoft Visual C++ 6.0,新建一个工程。然后将Parser Generator生成的两个文件myparser.c,myparser.h导入工程。(这里就不多说了^-^)现在要设置环境变量了,首先要导入Parser Generator的库文件和源文件。在工具->选项里要设置这些环境变量。 设置完这些文件后,还要在工程->设置里添加yl.lib库: 好,一切设置完毕,开始编译,编译通过后,就会生成yacc_vc.exe文件。假设有文件demo.txt,此文件和yacc_vc.exe在同一个目录,其内容如下:1+3*53*4-237- 9 *30 - 999在此目录的命令行下运行如下命令:yacc_vc.exe 单独lex文件的编译。 以下是一个单独的lex文件,实现一个简单的计算单词个数功能。%{ /************************************************************www.linmu100.com************************************************************/int wc = 0; /* word count */%}%%[a-zA-Z]+ { wc++; }/n|. { /* gobble up */ }%%int main(void){ int n = yylex(); return n;}int yywrap(void){ printf("word count: %d/n", wc); return 1;}我们用Parser Generator新建一个工程: 下一步默认完成即可。 这时,Parser Generator帮我们自动生成了一个mylexer.l文件,词法规则可以在这里加。 同样的,我们用上面展示的lex文件内容完全覆盖mylexer.l文件,编译后同样生成三个文件,然后用VC编译其中的myparser.c,myparser.h这两个文件。 VC的设置方法和上面编译单独yacc文件时的步骤完全一样,最终会生成一个可以计算文件单词数目的.exe文件。 yacc 和 lex整合文件的编译。以下分别是yacc文件和lex文件的内容,这两个文件共同实现了自定义的一个简单语法规则。 yacc文件内容: %{ /* www.linmu100.com */ #include #include void yyerror(const char *str) { fprintf(stderr,"error: %s/n",str); } int yywrap() { return 1; } main() { yyparse(); } char *heater="xl's test"; %} %token TOKHEATER TOKHEAT TOKTARGET TOKTEMPERATURE %union { int number; char *string; } %token STATE %token NUMBER %token WORD %% commands: | commands command ; command: heat_switch | target_set | heater_select ; heat_switch: TOKHEAT STATE { if($2) printf("/tHeater '%s' turned on/n", heater); else printf("/tHeat '%s' turned off/n", heater); } ; target_set: TOKTARGET TOKTEMPERATURE NUMBER { printf("/tHeater '%s' temperature set to %d/n",heater, $3); } ; heater_select: TOKHEATER WORD { printf("/tSelected heater '%s'/n",$2); heater=$2; } ; lex文件内容:%{