lex 筆記

lex 筆記

什麼是 lex

lex 是幫我們做 lexical analysis 的工具,它負責將 source code 切成一些 token。

Compile 方法

1lex rule.l
2gcc lex.yy.c -ll
3./a.out < input

lex 的格式

利用 %% 將 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 state3

Rule 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()
Built with Hugo
Theme Stack designed by Jimmy