美文网首页
Lex和Yacc

Lex和Yacc

作者: pittiw | 来源:发表于2017-05-21 17:46 被阅读0次

Lex和Yacc的分工

Lex用于词法分析,Yacc用于语法分析,二者可以单独使用,亦可配合工作。Yacc和Lex都是基于C语言的,语法极其相似,功能上Yacc和Lex有部分重叠,但是二者有一点区别:Yacc不能表达数字[0-9]+,也不能获得相应的数值;Yacc还不能忽略空白和注释。而这两点恰恰Lex可以办到。通常,Lex用于数字、空格和注释的解析,Yacc用于表达式解析。

Lex模板

/* C 和 Lex 的全局声明 */
%%

/* 模式(C 代码) */
%%

/* C 函数 */ 

Yacc模板

%{  
    /* C声明 */
    #include <stdio.h>
%}
/* yacc 定义 */
%%
/* 输入及其对应的动作的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);
}

如何编译与运行

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 快速入门
[2] Example of Formalising a Grammar for use with Lex & Yacc

相关文章

网友评论

      本文标题:Lex和Yacc

      本文链接:https://www.haomeiwen.com/subject/jjlmxxtx.html