![clip_image001[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image001%5B7%5D_thumb.jpg)
關(guān)于yacc 和 lex 和在下面鏈接的文章里已經(jīng)有所介紹了
/html/linuxshijie/20070909/80.html
鏈接中的文章還介紹了在linux下如何使用yacc和lex工具,下面主要是介紹yacc和lex在windows下的用法。
yacc和lex在windows已經(jīng)移植成功,其中常用的一個(gè)工具就是Parser Generator。這個(gè)工具使用yacc和lex能夠生成Visual C++,Borland C++,Other C/C++以及相關(guān)Java代碼。下面介紹一下這個(gè)工具是如何生成代碼并使用Visual C++編譯的。
注:關(guān)于Parser Generator的使用和配置,其實(shí)在Parser Generator Help中已經(jīng)有很詳細(xì)的介紹,感興趣的朋友可以去那里查到更多有用的信息。
首先要去http://www.bumblebeesoftware.com/downloads.htm下載Parser Generator。
安裝完畢后,我們可以在它的安裝目錄下找到一些例子以及編譯程序所需的庫(kù)文件和源文件,這些文件在編譯是很重要。
單獨(dú)yacc文件的編譯。
以下是一個(gè)單獨(dú)的yacc文件,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器功能。
%{
/************************************************************
www.linmu100.com
************************************************************/
#include <ctype.h>
#include <stdio.h>
#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創(chuàng)建一個(gè)工程,如下圖所示,注意紅圈部分的設(shè)置:
![clip_image002[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image002%5B7%5D_thumb.jpg)
然后設(shè)置文件,模板:
![clip_image003[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image003%5B7%5D_thumb.jpg)
其余按默認(rèn)完成即可:
![clip_image004[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image004%5B7%5D_thumb.jpg)
這時(shí),我們可以看到Parser Generator幫我們自動(dòng)生成了一個(gè)myparser.y文件,語(yǔ)法規(guī)則就可以在這里加了。
![clip_image005[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image005%5B7%5D_thumb.jpg)
現(xiàn)在我們把開(kāi)頭展示的yacc源碼完全覆蓋myparser.y文件,然后編譯,成功后會(huì)生成三個(gè)文件:myparser.c,myparser.h,myparser.v
好,現(xiàn)在我們要做的就是用vc來(lái)編譯myparser.c,myparser.h這兩個(gè)文件了。
打開(kāi)Microsoft Visual C++ 6.0,新建一個(gè)工程。
![clip_image006[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image006%5B7%5D_thumb.jpg)
然后將Parser Generator生成的兩個(gè)文件myparser.c,myparser.h導(dǎo)入工程。(這里就不多說(shuō)了^-^)
現(xiàn)在要設(shè)置環(huán)境變量了,首先要導(dǎo)入Parser Generator的庫(kù)文件和源文件。在工具->選項(xiàng)里要設(shè)置這些環(huán)境變量。
![clip_image007[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image007%5B7%5D_thumb.jpg)
![clip_image008[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image008%5B7%5D_thumb.jpg)
![clip_image009[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image009%5B7%5D_thumb.jpg)
設(shè)置完這些文件后,還要在工程->設(shè)置里添加yl.lib庫(kù):
![clip_image010[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image010%5B7%5D_thumb.jpg)
好,一切設(shè)置完畢,開(kāi)始編譯,編譯通過(guò)后,就會(huì)生成yacc_vc.exe文件。
假設(shè)有文件demo.txt,此文件和yacc_vc.exe在同一個(gè)目錄,其內(nèi)容如下:
1+3*5
3*4-23
7- 9 *30 - 999
在此目錄的命令行下運(yùn)行如下命令:yacc_vc.exe <demo.txt,即可得到計(jì)算結(jié)果:
![clip_image011[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image011%5B7%5D_thumb.jpg)
單獨(dú)lex文件的編譯。
以下是一個(gè)單獨(dú)的lex文件,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算單詞個(gè)數(shù)功能。
%{
/************************************************************
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新建一個(gè)工程:
![clip_image012[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image012%5B7%5D_thumb.jpg)
![clip_image013[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image013%5B7%5D_thumb.jpg)
下一步默認(rèn)完成即可。這時(shí),Parser Generator幫我們自動(dòng)生成了一個(gè)mylexer.l文件,詞法規(guī)則可以在這里加。
同樣的,我們用上面展示的lex文件內(nèi)容完全覆蓋mylexer.l文件,編譯后同樣生成三個(gè)文件,然后用VC編譯其中的myparser.c,myparser.h這兩個(gè)文件。
VC的設(shè)置方法和上面編譯單獨(dú)yacc文件時(shí)的步驟完全一樣,最終會(huì)生成一個(gè)可以計(jì)算文件單詞數(shù)目的.exe文件。
yacc 和 lex整合文件的編譯。
以下分別是yacc文件和lex文件的內(nèi)容,這兩個(gè)文件共同實(shí)現(xiàn)了自定義的一個(gè)簡(jiǎn)單語(yǔ)法規(guī)則。
yacc文件內(nèi)容:
%{
/*
www.linmu100.com
*/
#include <stdio.h>
#include <string.h>
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 <number> STATE
%token <number> NUMBER
%token <string> 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文件內(nèi)容:
%{
/*
www.linmu100.com
*/
#include <stdio.h>
#include <string.h>
#include "myparser.h" //注意,這里的頭文件要和Parser Generator生成的頭文件名一樣。
extern char *yytext;
%}
%%
[0-9]+ {yylval.number=atoi(yytext); return NUMBER;}
heater return TOKHEATER;
heat return TOKHEAT;
on|off {yylval.number=!strcmp(yytext,"on"); return STATE;}
target return TOKTARGET;
temperature return TOKTEMPERATURE;
[a-z0-9]+ {yylval.string=strdup(yytext);return WORD;}
\n /* ignore end of line */;
[ \t]+ /* ignore whitespace */;
%%
現(xiàn)在用Parser Generator創(chuàng)建新的工程:
![clip_image014[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image014%5B7%5D_thumb.jpg)
![clip_image015[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image015%5B7%5D_thumb.jpg)
![clip_image016[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image016%5B7%5D_thumb.jpg)
其余的步驟和上面編譯yacc時(shí)的步驟相同,最終可以生成both_y_l.exe文件,放一個(gè)demo.txt和both_y_l.exe在同一個(gè)目錄下,demo.txt內(nèi)容如下:
heat on
target temperature 99
heater asdfsieiwef99adsf
然后在此目錄的命令行下執(zhí)行both_y_l.exe <demo.txt得到:
![clip_image017[7]](http://m.shnenglu.com/images/cppblog_com/woaidongmao/WindowsLiveWriter/yacclexwindowsParserGenerator_FB8B/clip_image017%5B7%5D_thumb.jpg)
以上即為Parser Generator的使用以及如何用VC編譯。
/
/*-----Lex & Yacc ----www.linmu100.com ----*/
/
/*-----linux工具,Lex & Yacc,windows下操作----*/
/
/*-----linux配置,UNIX,開(kāi)源軟件,linux技術(shù),makefile----*/
/
/*----------------------@xiaolin--------------------*/