詞法分析器作為編譯器的一個重要組成部分,原理很簡單,代碼也都沒什麼技術含量,但是如果讓你手工寫一個詞法分析器,哪怕是一個簡單的詞法分析器,工作量無疑是巨大的。現代的詞法分析器一般都是依靠工具自動生成,這裡我們選用flex生成詞法分析器,下面是用到的flex的下載下傳位址。windows的環境的話,lex.exe檔案使我們所需要的工具。裡面的幫助文檔将教會你如何更好的使用flex。
學習編譯原理并非一定要做一個完美的編譯器,我們所需要的隻是了解編譯器的工作原理并能運用這些特性寫出更高效合法的程式,是以我們隻用lex的一些簡單功能寫一個簡單的詞法分析器來印證我們所學的知識。下圖是lex的使用步驟簡要說明:
這裡的源檔案是符合lex的語句,flex 的輸入檔案由三段組成,用一行中隻有%%來分隔。
定義;definition
%%
規則;rules
%%
使用者代碼;code
這個源檔案輸出的就是詞法分析器的C語言源程式,編譯這個.c的源程式生成的就是你所定義語言的詞法分析器。
這裡我們用一個簡單的例子來做一個簡單的詞法分析器,詞法規則符合《編譯原理及實踐教程》中描述的sample語言。
下面是Source檔案
%{
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
%}
DIGIT [-]
ID [a-z][a-z0-]*
%%
{DIGIT}+ {printf("整數: %s(%d)\n",yytext,atoi(yytext));}
{DIGIT}+"."{DIGIT}+ {printf("實數: %s(%g)\n",yytext,atof(yytext));}
if|then|begin|end|program|while|repeat {printf("關鍵字: %s\n",yytext);}
{ID} {printf("辨別符: %s\n",yytext);}
"+"|"-"|"*"|"/" {printf("運算符: %s\n",yytext);}
"{"[^}\n]*"}";
[\t\n\x20]+;
. {printf("不能識别的字元:%s\n",yytext);}
%%
int main(int argc,char **argv)
{
++argv;
--argc;
if(argc>) yyin=fopen(argv[],"r");
else yyin=stdin;
yylex();
return ;
}
int yywrap()
{
return ;
}
這裡我們把Source源檔案儲存為lex.l
通過在指令行模式下輸出指令 lex lex.l 生成lex.yy.c檔案,這就是我們的詞法分析器的源代碼了,打開看看,吃驚吧,這麼簡單的語言的詞法分析程式竟然需要這麼多代碼,還好我們不用手工寫。編譯這個源程式,得到 lex.yy.exe,測試一下
OK,簡單詞法分析器就完成了。
歡迎轉載,轉載注明出處