lex負責詞法解析,而yacc負責語法解析,其實說白了就是lex負責根據指定的正則表達式,將輸入的字符串匹配成一個一個的token,同時允許用戶將當前匹配到的字符串進行處理,並且允許返回一個標識當前token的標識碼。而yacc則負責進行語法解析,將一個個的token最終形成一個完整的語法。
lex和yacc類似的,分為三個部分
%{
這里可以寫任何的c代碼
比如一些初始化的狀態
%}
這里是一些的lex或者yacc的定義
比如lex里的%s
yacc里的%type %token %left %right %union
%%
這里可以寫任何的lex或者yacc代碼
%%
這里可以寫任何c代碼
這里需要注意的是,對於一個語法分析器來說,可以不使用lex而自己根據需要來完成,但是使用lex可以直接使用正則來進行匹配,使得整個過程更加簡單。而lex與yacc之間的通信就是靠%union里定義的聯合體來完成。其實%union里定義的聯合體最終會被生成一個叫yylval的全局變量,這個全局變量可以在lex和yacc之間傳遞變量。
%type<xxx> 這里的xxx必須是%union里定義的一個成員變量,那么%type<xxx> 里定義的類型就會被存儲這個成員變量里
%token<xxx> 與%type類似,只是它所代表的是token而已
$$代表當前的type所計算的最終結果,而$1代表type組成式中的第一個變量的值,以此類推
lex定義了一種叫state的東西,其實這個東西很容易理解,比如class abc{} 與function xxx{}同樣是{},它們含意其實是不同的,一個代表了類,一個代表了方法定義,因此state這個東西就是定義當前的一個狀態,用%s來進行定義。通過BEGIN來開始
END來結束
注:lex->flex yacc->bison 這是兩個升級。
mysql中的sql分析器就只用了yacc而沒有使用lex,go的語法分析器也一樣,只使用了bison,而沒有使用flex;而php則同時使用了flex和bison。目前來看,應該是正則在效率上還是有些問題的,因此對於效率要求比較高的一些應用寧願自己來寫lex功能,而不會直接使用lex.