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.