Lex入门
Lex主要功能是生成一個詞法分析器(scanner)的 C 源碼,描述規則采用正則表達式(regular expression)。描述詞法分析器的文件 *.l 經過lex編譯后,生成一個lex.yy.c 的文件,然后由 C 編譯器編譯生成一個詞法分析器。詞法分析器,簡言之,就是將輸入的各種符號,轉化成相應的標識符(token),轉化后的標識符很容易被后續階段處理,如YACC 或 Bison,過程如圖
,“lex”和“yacc”這兩個名字所代表的也包括這些工具的 GNU 版本 flex 和 bison。 給出的代碼應該適用于所有主流版本,比如 MKS yacc。它完全是一個融洽的大家族!
Flex (fast lexical analyser generator) 是 Lex 的另一個替代品。它經常和自由軟件 Bison 語法分析器生成器 一起使用。Flex 最初由 Vern Paxson 于 1987 年用C語言寫成。Flex手冊里對 Flex 描述如下:
Flex是一個生成掃描器的工具,能夠識別文本中的詞法模式。Flex 讀入給定的輸入文件,如果沒有給定文件名的話,則從標準輸入讀取,從而獲得一個關于需要生成的掃描器的描述。此描述叫做規則,由正則表達式和 C代碼對組成。Flex 的輸出是一個 C 代碼文件——lex.yy.c——其中定義了yylex() 函數。編譯輸出文件并且和 -lfl 庫鏈接生成一個可執行文件。當運行可執行文件的時候,它分析輸入文件,為每一個正則表達式尋找匹配。當發現一個匹配時,它執行與此正則表達式相關的C代碼。Flex 不是GNU工程,但是GNU為Flex 寫了手冊。
總之,Flex 是詞法分析工具,它讀取輸入源文件,然后生成 C 語言源程序,通常默認的是 "lex.yy.c", 該文件中包含 yylex( ) 例程,并且可以被 C 編譯器編譯鏈接為可執行文件,在該詞法分析器運行時,它會根據已定義的規則,在遇到一定的匹配模式時執行相應的 C 代碼,從而完成詞法分析動作
gcc lex.yy.c 報錯:
In function `yylex':
lex.yy.c:(.text+0x39b): undefined reference to `yywrap'
/tmp/ccIx8oEA.o: In function `input':
lex.yy.c:(.text+0xcdb): undefined reference to `yywrap'
The scanner calls this function on end of file, so you can point it to another file and continue scanning its contents. If you don't need this, use
%option noyywrap (一般在文件開頭加,類似這樣
%option noyywrap
%{
/* * * * * * * * * * * *
* * * DEFINITIONS * * *
* * * * * * * * * * * */
%}
)
or link with-lflto use the default yywrap() function in the libraryfl.(就是gcc lex.yy.c -lfl )
還有一種辦法,我們自己寫一個不做什么的yywrap()函數;
int yywrap()
{
return 1;
}
以上3中解決方案都可以。
輸入幾行字,計算行數,單詞數和字符數.
%option noyywrap
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n { chars++; lines++; }
. { chars++; }
%%
main(int argc, char **argv)
{
yylex();
printf("%8d%8d%8d\n", lines, words, chars);
}
{}內的是c編寫的動作
按照下面過程編譯。
#flex test.l
#gcc lex.yy.c -o main.out
#./main.out (不要再這行接著輸入文字,flex不會計數的)
hello world
you can say
按ctrl+d結束
輸出結果 2 5 24
修改上面的例子,將正則表達式放在全局聲明中:
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
mywords [a-zA-Z]+
mylines \n
mychars .
%%
{mywords} { words++; chars += strlen(yytext); }
{mylines} { chars++; lines++; }
{mychars} { chars++; }
%%
main(int argc, char **argv)
{
yylex();
printf("%8d%8d%8d\n", lines, words, chars);
}
小知識:
flex有很多選項,我們不想使用默認的lex.yy.c名字,加上
-o lexname 就可以了。
flex -o b.yy.c b.l
可以使用man flex查看幫助
The Scanner as Coroutine(協同程序)
即怎樣將掃描到的標記給其他程序使用,下面的例子,希望掃描到+ 或 -時做一個特殊輸出。
當調用yylex時,若掃描到return對應的標記時,yylex返回,且值就為return后的值;
若沒掃描到return對應的標記,yylex繼續執行,不返回。
下次調用自動從前一次的掃描位置處開始。
%option noyywrap
%{
enum yytokentype{
ADD=259,
SUB=260
};
%}
myadd "+"
mysub "-"
myother .
%%
{myadd} { return ADD;}
{mysub} { return SUB;}
{myother} {printf("Mystery character\n");}
%%
main(int argc,char **argv)
{
int token;
while(token=yylex())
{
if(token==ADD||token==SUB )
{//yylex的返回值只能是ADD 或 SUB.
printf("meet + or -\n");
}
else {
printf("this else statement will not be printed, \
because if yylex return,the retrun value must be ADD or SUB.");
}
}
}
$./b.out
h+f-w
Mystery character
meet + or -
Mystery character
meet + or -
Mystery character
參考:http://www.cnblogs.com/vestinfo/archive/2012/09/29/2708931.html
http://xiaoxia.org/2011/10/24/writing-a-compiler-learning-gnu-flex-write-a-lexical-analyzer/
http://web.eecs.utk.edu/~bvz/cs461/notes/flex/
http://www.ibm.com/developerworks/cn/linux/sdk/lex/
http://www.ibm.com/developerworks/cn/linux/l-lexyac.html
http://course.cug.edu.cn/bianyi/shiyan/CHAPTER/f1.htm
http://wenku.baidu.com/view/5b46758da0116c175f0e4898.html
總結
- 上一篇: 狡兔三窟是什么意思(狡兔三窟成语故事)
- 下一篇: 支付接口的接入思路和注意要点