Lex和Yacc的分工
Lex用于詞法分析,Yacc用于語(yǔ)法分析,二者可以單獨(dú)使用名惩,亦可配合工作蛮拔。Yacc和Lex都是基于C語(yǔ)言的,語(yǔ)法極其相似晃财,功能上Yacc和Lex有部分重疊叨橱,但是二者有一點(diǎn)區(qū)別:Yacc不能表達(dá)數(shù)字[0-9]+,也不能獲得相應(yīng)的數(shù)值断盛;Yacc還不能忽略空白和注釋罗洗。而這兩點(diǎn)恰恰Lex可以辦到。通常钢猛,Lex用于數(shù)字伙菜、空格和注釋的解析,Yacc用于表達(dá)式解析命迈。
Lex模板
/* C 和 Lex 的全局聲明 */
%%
/* 模式(C 代碼) */
%%
/* C 函數(shù) */
Yacc模板
%{
/* C聲明 */
#include <stdio.h>
%}
/* yacc 定義 */
%%
/* 輸入及其對(duì)應(yīng)的動(dòng)作的C描述 */
%%
/* C 代碼 */
int main(void)
{
return yyparse();
}
int yylex(void)
{
return getchar();
}
void yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
}
%%
示例程序
Lex name.lex
%{
#include "y.tab.h"
#include <stdio.h>
#include <string.h>
extern char* yylval;
%}
char [A-Za-z]
num [0-9]
eq [=]
name {char}+
age {num}+
%%
{name} { yylval = strdup(yytext); return NAME; }
{eq} { return EQ; }
{age} { yylval = strdup(yytext); return AGE; }
%%
int yywrap()
{
return 1;
}
Yacc name.y
%{
#include <stdio.h>
#define YYSTYPE char* /*a Yacc variable which has the value of returned token */
%}
%token NAME EQ AGE
%%
file: record file | record;
record: NAME EQ AGE
{
printf("%s is now %s years old!!1", $1, $3);
};
%%
int main()
{
yyparse();
return 0;
}
int yyerror(char* msg)
{
printf("Error: %s encountered \n", msg);
}
如何編譯與運(yùn)行
lex : .lex -> lex.yy.c
yacc : .y -> y.tab.c + y.tab.h
gcc : lex.yy.c + y.tab.h + lex.yy.cc -> a.out
a.out : input -> result
# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.2 (Maipo)
# lex name.lex
# yacc -d name.y
# cc lex.yy.c y.tab.h y.tab.c
# ./a.out
hello=3
hello is now 3 years old!!1
參考
[1] Yacc 與 Lex 快速入門(mén)
[2] Example of Formalising a Grammar for use with Lex & Yacc