2016年3月9日 星期三

LEX 掃描器產生器 上手筆記


這張圖片純吋只是拿來優化Blog的SEO而已,Google 『Lexer』居然找到意料之外的東西...

這學期學校教了Compiler,老師在講解Scanner的時候以Lex這個工具為例介紹他的工作原理
只好來惡補一下這個工具怎麼使用了

Lex, 其實是『Lexer』(分析器)的縮寫, 利用正規表達式將規則寫在*.l的檔案中餵給lex
它會產生一個依據此規則的Scanner的原始碼

以下的範例是來自於linux.com中關於Lex和Yacc這兩個工具的介紹
如果需要更詳盡的介紹可以前往觀看

以下是範例輸入,將會被我們等下製作出的Scanner宰割

logging {
        category lame-servers { null; };
        category cname { null; };
};

zone "." {
        type hint;
        file "/etc/bind/db.root";
};

根據上面的範例輸入,我們可以歸納出種Token的型態:
WORDs 一般的單字
FILENAME 檔名或檔案路徑
QUOTE 雙引號
BRACE 大括號
SEMICOLON 分號

接下來是產生Scanner的lex檔案example.l

%{
 #include 
%}
%%
[a-zA-Z][a-zA-Z0-9]* printf("WORD");
[a-zA-Z0-9\/.-]+ printf("FILENAME");
\" printf("QUOTE");
\{|\} printf("EMBRACE");
; printf("semicolon");
\n printf("\n");
%%
一個lex檔案中會有三個段落,段落之間以%%區隔
第一個段落是Definition,例如Inlcude檔案和宣告變數等等
第二個段落是Scanner的規則和對應的動作
第三段是使用者自由增加的code,會照貼到等等要編譯的scanner的原始碼中

產生Scanner方式

$ lex example.l
會產生scanner的C語言原始碼名為lex.yy.c,編譯它
$ gcc lex.yy.c -o example -ll
編譯產生的執行檔就是Scanner了
$ cat ./input.txt | ./example