什麼是 lex
lex 是幫我們做 lexical analysis 的工具,它負責將 source code 切成一些 token。
Compile 方法
1lex rule.l
2gcc lex.yy.c -ll
3./a.out < inputlex 的格式
利用 %% 將 code 切成三個區段,第一個和第二個是必須的。
1definition section
2%%
3rule section
4%%
5user subroutine最簡單的 lex 程式
1%%Definition Section
- 寫在此區的 C 程式碼需要加上 %{和%},例如放 header 和全域變數等等。
- 可以給於一些定義。
1digit [0-9]
2letter [a-zA-Z]
3space [ \t]+
4identifier {letter}({digit}|{letter})*
5integer 0|([1-9]{digit}*)- 可以定義一些 State,用 %s或%x,預設的 State 稱為INITIAL。
1%s state1 state2 state3Rule Section
- 前面那一項是要寫正規表示法。
- 比對的規則是先找最長的 rule,遇到一樣長的時候,找最前面的 rule。
1/* 以下這份 code 可以將程式的空白和換行移除。 */
2{space}  { ; }
3\n       { ; }
4.        { ECHO; }User Subroutine
- 用來寫一些 function。
- 可以自定義 main(),若沒有則是用預設的main()。
1main() {
2    yylex();
3}正規表示法
| regular expression | definition | 
|---|---|
| . | 一個字元( \n以外的所有字元) | 
| * | 重複零次以上 | 
| + | 重複一次以上 | 
| ? | 零次或一次 | 
| ^ | 放在 []中,表示不包含 | 
| ^ | 放在開頭,表示一行的開頭 | 
| $ | 放在結尾,表示一行的結尾 | 
| {a, b} | 重複 a ~ b 次 | 
| ` | ` | 
| / | 表示前面的表示法需要接在後面的表示法之前,yytext 只匹配到前面 | 
%s 和 %x 的區別
- 使用 %s時,沒有定義狀態的 rule,可以代表所有狀態。
- 使用 %x時,則是 exclusive,沒有定義狀態的只會配到INITIAL。
Test Case
1/*
2comment
3*/Example
- 若運行以下程式碼,會輸出 id,正確的 rule 需改成<INITIAL>{identifier},否則按規則將匹配到最長的 rule。
1%s COMMENT
2
3%%
4
5"/*" { BEGIN COMMENT; }
6<COMMENT>. { ; }
7<COMMENT>"*/" { ; }
8{identifier} { printf("id"); }- 以下是正確的寫法,只要用 %x就可以避免上述情況。
1%x COMMENT
2
3%%
4
5"/*" { BEGIN COMMENT; }
6<COMMENT>. { ; }
7<COMMENT>"*/" { ; }
8{identifier} { printf("id"); }特殊指令
- ECHO,- REJECT,- BEGIN。
Lex Libiary
- yytext
- yyleng
- yyin
- yyout
- yylex()
- yymore()
- yyless(n)
- yywrap()