说明:以下内容来自《PostgreSQL数据库内核分析》P190
Lex用来生成扫描器,其工作是识别一个一个的模式,比如数字,字符串,特殊符号等,然后将其传给Yacc.
Yacc则用于生成语法分析器,它识别模式的组合,即语法,它们通过共同的符号表传递标识符,通过内置变量yylval传递表示的值。
Lex是通用的用于生成扫描器的工具,它利用正则表达式来表达模式。lex、yacc 均包含三部分:定义段、规则段和、代码段
(1)定义段可以包含任意的C语言文件,符号说明,其代码会被直接拷贝到生成的扫描器代码文件中
声明示例如下
%{
...
%}
(2)规则段利用正则表达式来匹配模式,每当成功匹配一个模式,就对应其后“{ }” 中的代码。
语法规则示例如下
%%
...
%%
(3)代码段可以是任意的C代码,但是其中必须要调用Lex提供的函数
正常的C语言代码
[wln@localhost 01]$ cat calculator.l
%{#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
[\t] ;
\n return 0;
. return yytext[0];
%%
[wln@localhost 01]$ cat calculator.y
%{
#include <<stdio.h>>
%}
%token NAME NUMBER
%left '*''/''+' '-'
%start statement
%%
statement:NAME '=' expression
| expression{printf("=%d\n",$1);}
;
expression:NUMBER '+' NUMBER{$$=$1+$3;}
| NUMBER '-' NUMBER{$$=$1-$3;}
| NUMBER '*' NUMBER{$$=$1*$3;}
| NUMBER '/' NUMBER{$$=$1/$3;}
| NUMBER{$$=$1;}
;
%%
extern int yylineno;
extern FILE *yyin;
int yyerror(char* msg)
{
printf("Error: %s encountered at line number:%d\n", msg, yylineno);
}
main()
{
do
{
yyparse();
}
while(!feof(yyin));
}
[wln@localhost 01]$ yacc -d calculator.y
[wln@localhost 01]$ lex calculator.l
[wln@localhost 01]$ cc -o calculator y.tab.c lex.yy.c -ll
参考:
1.http://www.ibm.com/developerworks/cn/linux/sdk/lex/
2.http://www.ibm.com/developerworks/library/l-lexyac/index.html
3.http://www.ibm.com/developerworks/cn/linux/sdk/lex/