編譯原理 - 實驗二 - FLEX詞法分析器


FLEX詞法分析器

一、Lex和Yacc介紹

Lex 是一種生成掃描器的工具。掃描器是一種識別文本中的詞匯模式的程序。 一種匹配的常規表達式可能會包含相關的動作。這一動作可能還包括返回一個標記。 當 Lex 接收到文件或文本形式的輸入時,它試圖將文本與常規表達式進行匹配。 它一次讀入一個輸入字符,直到找到一個匹配的模式。 如果能夠找到一個匹配的模式,Lex 就執行相關的動作(可能包括返回一個標記)。 另一方面,如果沒有可以匹配的常規表達式,將會停止進一步的處理,Lex 將顯示一個錯誤消息。

Yacc代表 Yet Another Compiler Compiler 。 Yacc 的 GNU 版叫做 Bison。它是一種工具,將任何一種編程語言的所有語法翻譯成針對此種語言的 Yacc 語 法解析器。 

(下載下載flex和bison。網址分別是http://gnuwin32.sourceforge.net/packages/flex.htm和http://gnuwin32.sourceforge.net/packages/bison.htm。)

二、配置環境(win7)

①  下載flex和bison並安裝到D:\GnuWin32(盡量是根目錄)

②  由於我們使用的flex和bison都是GNU的工具,所以為了方便,采用的C/C++

編譯器也 采用GNU的編譯器GCC,當然我們需要的也是Windows版本的GCC了。所以提前准備好VC 6.0

③  檢驗是否可以進行lex文件編譯

1.新建文本文件,更改名稱為lex.l,敲入下面代碼

%{

int yywrap(void);

%}

%%

%%

int yywrap(void)

{

return 1;

}

2.新建文本文件,更改名稱為yacc.y,敲入下面代碼

%{

void yyerror(const char *s);

%}

%%

program:

;

%%

void yyerror(const char *s)

{

}

int main()

{

yyparse();

return 0;

}

我們暫且不討論上面代碼的意思。

打開控制台,進入到剛才所建立文件(lex.l,yacc.y)所在的文件夾。

1.輸入 flex lex.l

2.輸入 bison yacc.y

如果我們看到當前文件夾上多了兩個文件(yacc.tab.c,lex.yy.c),那么說明lex&&yacc已經安裝配置成功,接下來就可以進行實驗了。

 三、課本實例

1.  按課本p58 3.7.3代碼,保存testscan.lex文件,然后放到與flex相同的文件夾下,然后進入DOS下,輸入flex testscan.lex 並回車,即可生成lex.yy.c文件

2.  用C編譯器(VC 6.0)編譯並產生lexyy.exe

3.  建好aaa.txt輸入文件,進入DOS下,進入到lexyy.exe所在目錄,輸入lexyy.exe aaa.txt bbb.txt即可。

{
int a;
a=10;
}

通過分析后:

{, {

int, int
NUM, a
;, ;

NUM, a
=, =
ID, 10
;, ;

}, }

4.  課本p61 7

按題目要求適當修改代碼,然后在進入DOS下,進入到lexyy.exe所在目錄,輸入lexyy.exe abc.txt abcdef.txt,再打開abcdef.txt即可看到結果

int i=10;
do{
printf(i);
i++;
}while(i!>10)
if(1<2&&2<4)
else(1||2)

分析后:

int, int
NUM, i
=, =
ID, 10
;, ;

NUM, do
{, {

NUM, printf
(, (
NUM, i
), )
;, ;

NUM, i
+, +
+, +
;, ;

}, }
while, while
(, (
NUM, i
!, !
>, >
ID, 10
), )

if, if
(, (
ID, 1
<, <
ID, 2
&&ID, 2
<, <
ID, 4
), )

else, else
(, (
ID, 1
||ID, 2
), )

五、代碼

%{
#include<stdio.h>
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
%}

digit [0-9]
number {digit}+
letter [a-zA-Z]
identifier {letter}({letter}|{digit})*
newline [\n]
whitespace [\t]+
%%
"if" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"else" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"for" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"while" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"int" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"+" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"-" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"*" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"/" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"<" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
">" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"(" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
")" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"{" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"}" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
";" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
":" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"'" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"," {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"!" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"==" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
">=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"<=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
"!=" {fprintf(yyout,"%s, %s\n", yytext,yytext);}
{number} {fprintf(yyout,"%s, %s\n", "ID",yytext);}
{identifier} {fprintf(yyout,"%s, %s\n", "NUM",yytext);}
{whitespace} {/*跳過空白*/}
"/*" {char c ;
int done=FALSE;
do{
while((c=input())!='*');
while((c=input())=='*');
if(c=='/') done=TRUE;
}while(!done);
}
{fprintf(yyout,"%d, %s\n", 0,yytext);}
%%

main(argc,argv)
int argc;
char **argv;
{
++argv,--argc;
if(argc>0)
yyin=fopen(argv[0],"r");
else
yyin=stdin;
++argv,--argc;
if(argc>0)
yyout=fopen(argv[0],"w");
else
yyout=stdout;
yylex();
}
int yywrap()
{
return 1;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM