Win flex-bison 的簡單使用
學習編譯原理的朋友,都會看到書中提到的 lex & yacc 或 flex & bison 工具組合。這兩組工具在 Unix, Linux, BSD 上使用不會有太大的問題,但在 Windows 上使用通常需要安裝 MinGW+ (Msys GnuWin 或Msys2 ) 或者Cygwin。Win flex-bison 提供了 flex bison for Windows 的另外一種移植,將GNU m4巨集處理器原始碼整合進 win flex-bison ,不依賴Msys,Msys2,Cygwin 提供的模擬類 Unix 執行環境,不依賴GNU m4巨集處理器便可生成 C 目標檔案。
flex 見
http://sourceforge.net/projects/flex/
bison 見 http://www.gnu.org/software/bison/
目前,Msys GnuWin 上的 flex 2.5.35 和 bison (GNU Bison) 2.4.2 版本太陳舊了, N年沒更新了。Msys2 (
http://sourceforge.net/projects/msys2/ ) 上的版本新, flex2.5.38 和 bison 3.0.2
Win flex-bison 見 http://sourceforge.net/projects/winflexbison/
Win flex-bison is a port Flex & Bison tools to the Windows platform
下面以 Win flex-bison 2.5.1和《flex & bison》第一章的簡單計算器fb1-5為例,簡單介紹如何使用。
首先從 http://sourceforge.net/projects/winflexbison/ 下載已經編譯好的壓縮檔案 win_flex_bison-2.5.1.zip(不到700kb),
Update: 2014-01-04
Description
Win flex-bison is a windows port the Flex(the fast lexical analyser) and Bison (GNU parser generator). win_flex based onFlex version 2.5.37 source code and win_bisonbased on Bison version 2.7 and they depend on system libraries only.
UPDATE1: Bison version 3.0 available in Files section in win_flex_bison-2.5.zippackage.
UPDATE2: Now "winflexbison" available as package in Chocolatey (http://chocolatey.org/packages/winflexbison)
Categories
License
GNUGeneral Public License version 3.0 (GPLv3)
解壓到某一資料夾(如 winFlexBison),將這個資料夾增加到 path 環境變數中,就可以命令列使用了。
Bison規則描述檔案 fb1-5.y
/* Companionsource code for "flex & bison", published by O'Reilly
* Media, ISBN 978-0-596-15597-1
* Copyright (c) 2009, Taughannock Networks.All rights reserved.
* See the README file for license conditionsand contact info.
* $Header: /home/johnl/flnb/code/RCS/fb1-5.y,v2.1 2009/11/08 02:53:18 johnl Exp $
*/
/* simplestversion of calculator */
%{
# include <stdio.h>
%}
/* declare tokens*/
%token NUMBER
%token ADD SUB MULDIV ABS
%token OP CP
%token EOL
%%
calclist: /*nothing */
| calclist exp EOL { printf("= %d\n>", $2); }
| calclist EOL { printf("> "); }/* blank line or a comment */
;
exp: factor
| exp ADD exp { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
| exp ABS factor { $$ = $1 | $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER
| ABS term { $$ = $2 >= 0? $2 : - $2; }
| OP exp CP { $$ = $2; }
;
%%
main()
{
printf("> ");
yyparse();
}
yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
Flex詞法分析檔案 fb1-5.l
/* Companionsource code for "flex & bison", published by O'Reilly
* Media, ISBN 978-0-596-15597-1
* Copyright (c) 2009, Taughannock Networks.All rights reserved.
* See the README file for license conditionsand contact info.
* $Header: /home/johnl/flnb/code/RCS/fb1-5.l,v2.1 2009/11/08 02:53:18 johnl Exp $
*/
/* recognizetokens for the calculator and print them out */
%{
# include"fb1-5.tab.h"
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP; }
")" { return CP; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
"//".*
[ \t] { /* ignore white space */ }
. { yyerror("Mystery character%c\n", *yytext); }
%%
手工執行以下命令
win_bison -d fb1-5.y
生成 fb1-5.tab.h 和fb1-5.tab.c 檔案
win_flex --nounistdfb1-5.l 或win_flex --wincompat fb1-5.l
生成 lex.yy.c 檔案。--nounistd 和 --wincompat 選項使生成的 lex.yy.c 不依賴<unistd.h> 可以用 VC 編譯,否則就只能用 gcc 編譯了。
--wincompat 為 win_flex 所增加的設定選項,在 flex --nounistd (do not include <unistd.h> ) 的基礎上,減少 VC 的
compile warning (uses <io.h> instead of <unistd.h> and _isatty, _fileno functions ), 另外在生成的lex.yy.c 檔案中新增:
/*windows compatibility case*/
#include <io.h>
#define isatty _isatty
#define fileno _fileno
其實,也可這樣解決 :warning C4013: “isatty” undefined; assuming extern returning int
在 .l 檔案中包含 # include <io.h>
warning C4013: “strdup” undefined; assuming extern returning int
在 .l 或 .y 檔案中包含 # include <string.h>
warning C4996: 'isatty': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _isatty. See online help for details.
warning C4996: 'fileno': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _fileno. See online help for details.
warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details.
在 VC 新增 _CRT_NONSTDC_NO_DEPRECATE 編譯巨集定義,見 http://msdn.microsoft.com/en-us/library/ms235384.aspx 說明。
為了專案管理方便可將 lex.yy.c 重新命名為 fb1-5.c ,用 cl 手工編譯
cl fb1-5.cfb1-5.tab.c libfl.a 或 cl fb1-5.c fb1-5.tab.c libfl.lib
生成 fb1-5.exe ,由於用到 yywrap() 需要連結 flex 的 libfl.a 庫。用VC編譯的話,可以將 libfl.a 重名為libfl.lib 更直觀。
執行一下fb1-5.exe
你也可以建立一個MakeFile檔案 makefile.mak
# Build a Simple Calc with fb1-5.y and fb1-5.l
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
CC=cl
CFLAGS=/nologo /DNDEBUG /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /O2 /W3
LD=link
LDFLAGS=/nologo
LIBS=libfl.lib
MOVE=move /Y
ALL : fb1-5.exe
CLEAN :
-@erase "*.obj"
-@erase "fb1-5.c"
-@erase "fb1-5.tab.c"
-@erase "fb1-5.tab.h"
-@erase "fb1-5.exe"
OBJS=\
fb1-5.obj \
fb1-5.tab.obj \
"fb1-5.tab.c" : fb1-5.y
if not exist "$@/$(NULL)" win_bison -d $**
"fb1-5.tab.h" : fb1-5.y
if not exist "$@/$(NULL)" win_bison -d $**
"fb1-5.c" : fb1-5.l
if not exist "$@/$(NULL)" win_flex --nounistd $** && $(MOVE) lex.yy.c $@
"fb1-5.exe" : $(OBJS)
$(LD) $(LDFLAGS) /out:$@ $** $(LIBS)
"fb1-5.obj" : fb1-5.c fb1-5.tab.h
$(CC) $(CFLAGS) /c fb1-5.c
"fb1-5.tab.obj" : fb1-5.tab.c fb1-5.tab.h
$(CC) $(CFLAGS) /c fb1-5.tab.c
用 nmake /f makefile.mak來構建。
另外一個國外圖文並茂的教程為 Using flex and bison in MSVC++
http://www.di-mgt.com.au/flex_and_bison_in_msvc.html
本文就是從那演化來的。
libfl.a ( v2.5.37 );從 GnuWin ,Msys , Msys2 中提取
Msys2 http://sourceforge.net/projects/msys2/
也可以從 http://pan.baidu.com/s/1eQcKMgM 下載。
不連結 libfl.a 例程可以採用以下方式:
%{
# include "fb1-5.tab.h"
%}
%option noyywrap
%%
或 提供 yywrap() 例項
int yywrap()
{
return 1;
}
或在 flex 執行選項增加 --noyywrap 選項。
都可以不用連結 flex 提供的 libfl.a 或 libfl.lib 例程( It contains versions of main() and yywrap(). )。
細心的話,你會發現 fb1-5.l 中的 yyerror() 呼叫2個引數,不同於 fb1-5.y 中的 yyerror(char *s),但的確呼叫的是yyerror(char *s),並編譯通過,並生成執行檔案。
執行中輸入出錯時,出錯資訊只是輸出:
> error: Mystery character %c
與原設想的有出入,沒有多大實用性。
這時,你可在 fb1-5.l 檔案中增加 %option yylineno 選項 ,重新處理輸出出錯資訊。
. { printf("error: Mystery character %c(line:%d)\n", *yytext, yylineno); }
接下來,在 fb1-5.y 中增加正負號處理,即增加一元操作符 +,-
term: NUMBER
| SUB term { $$ = - $2; /* unary minus */ }
| ADD term { $$ = $2; /* unary plus */ }
| ABS term { $$ = $2 >= 0? $2 : - $2; }
| OP exp CP { $$ = $2; } ;
同理,可以根據需要,新增想要的操作符和函式。
修改後完整的原始檔如下:
fb1-5.l
/* Companion source code for "flex & bison", published by O'Reilly
* Media, ISBN 978-0-596-15597-1
* Copyright (c) 2009, Taughannock Networks. All rights reserved.
* See the README file for license conditions and contact info.
* $Header: /home/johnl/flnb/code/RCS/fb1-5.l,v 2.1 2009/11/08 02:53:18 johnl Exp $
*/
/* recognize tokens for the calculator and print them out */
%{
#include <io.h>
# include "fb1-5.tab.h"
%}
%option noyywrap
%option yylineno
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP; }
")" { return CP; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
"//".*
[ \t] { /* ignore white space */ }
. { printf("error: Mystery character %c(line:%d)\n", *yytext, yylineno); }
%%
fb1-5.y
/* Companion source code for "flex & bison", published by O'Reilly
* Media, ISBN 978-0-596-15597-1
* Copyright (c) 2009, Taughannock Networks. All rights reserved.
* See the README file for license conditions and contact info.
* $Header: /home/johnl/flnb/code/RCS/fb1-5.y,v 2.1 2009/11/08 02:53:18 johnl Exp $
*/
/* simplest version of calculator */
%{
#include <stdio.h>
void yyerror(char *s);
%}
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL
%%
calclist: /* nothing */
| calclist exp EOL { printf("= %d\n> ", $2); }
| calclist EOL { printf("> "); } /* blank line or a comment */
;
exp: factor
| exp ADD exp { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
| exp ABS factor { $$ = $1 | $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER
| SUB term { $$ = - $2; /* unary minus */ }
| ADD term { $$ = $2; /* unary plus */ }
| ABS term { $$ = $2 >= 0? $2 : - $2; }
| OP exp CP { $$ = $2; }
;
%%
int main( void )
{
printf("> ");
yyparse();
return 0;
}
void yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
makefile.mak (適用於Msys2中的 flex& bison 在 Windows + VC, 修改相應 LEX , YACC 變數,可用於 win flex-bison )# Build a Simple Calc with fb1-5.y and fb1-5.l
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
CC=cl
CFLAGS=/nologo /DNDEBUG /D_CRT_SECURE_NO_WARNINGS /O2 /W3
LD=cl
LDFLAGS=/nologo /link
MOVE=move /Y
LEX=flex
YACC=bison
ALL : fb1-5.exe
CLEAN :
-@erase "*.obj"
-@erase "fb1-5.c"
-@erase "fb1-5.tab.c"
-@erase "fb1-5.tab.h"
-@erase "fb1-5.exe"
OBJS=\
fb1-5.obj \
fb1-5.tab.obj \
"fb1-5.tab.c" : fb1-5.y
if not exist "$@/$(NULL)" $(YACC) -d $**
"fb1-5.tab.h" : fb1-5.y
if not exist "$@/$(NULL)" $(YACC) -d $**
"fb1-5.c" : fb1-5.l
if not exist "$@/$(NULL)" $(LEX) --nounistd $** && $(MOVE) lex.yy.c $@
"fb1-5.exe" : $(OBJS)
$(LD) $** $(LDFLAGS) /out:$@
"fb1-5.obj" : fb1-5.c fb1-5.tab.h
$(CC) $(CFLAGS) /c fb1-5.c
"fb1-5.tab.obj" : fb1-5.tab.c fb1-5.tab.h
$(CC) $(CFLAGS) /c fb1-5.tab.c
在 MSYS2 shell 中執行結果
Win flex_bison 2.5.1 在 2014.3.27 增加了 custom_build_rules 資料夾
其中 how_to_use.txt 中為 https://sourceforge.net/p/winflexbison/wiki/Visual%20Studio%20custom%20build%20rules/
"Visual Studio custom build rules" Wiki Pages
These steps help you setup custom build rules for Visual Studio 2010 and up.
內容與 http://www.di-mgt.com.au/flex_and_bison_in_msvc.html 差不多,但是沒有 如何增加命令引數 的步驟,令人不解!
轉載本文請註明來自 http://blog.csdn.net/gocad/article/details/21866627
相關文章
- Kdevelop的簡單使用和簡單除錯dev除錯
- postman的簡單使用Postman
- OD的簡單使用
- RocketMQ的簡單使用MQ
- docker的簡單使用Docker
- SXSSFWorkbook的簡單使用
- peewee的簡單使用
- LayUi的簡單使用UI
- Vue簡單的使用Vue
- uuid的簡單使用UI
- git的簡單使用Git
- RecyclerView的簡單使用View
- ConcurrentLinkedQueue的簡單使用
- Handler的簡單使用
- Flatbuffer的簡單使用
- Mackdown簡單的使用教程Mac
- shell script的簡單使用
- vue框架的簡單使用Vue框架
- 協程的簡單使用
- matplotlib簡單的使用(二)
- Maven 私服的簡單使用Maven
- 使用tensorboard的簡單方法ORB
- react hooks 的簡單使用ReactHook
- BootStrapValidate 簡單使用boot
- GCDAsyncSocket 簡單使用GC
- gorm 簡單使用GoORM
- JPTabBar簡單使用tabBar
- Drozer簡單使用
- jq 簡單使用
- git簡單使用Git
- OpenFeign簡單使用
- LinqPad簡單使用
- Badger簡單使用
- 簡單使用 rocketmqMQ
- kvm簡單使用
- Quartz 簡單使用quartz
- kustomize簡單使用
- apijson簡單使用APIJSON
- Github 簡單使用Github