什麼是 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
yytextyylengyyinyyoutyylex()yymore()yyless(n)yywrap()