编译原理学习笔记——Lex&YACC(一)

  编译原理课程主要分为两种,一种侧重理论,一种侧重实现(implemention)。而LEX&YACCl是一个可以很方便实践编译原理的有力工具,结合龙书来学习是个不错的选择。如果你已经使用了一段时间的Unix,你会发现很多神奇的YACC/LEX程序,或则你是一个GNU/linux的程序员,则是Flex & Bison, Flex 是Vern Paxon有用lex实现的,而Bison则是GNU版本的YACC,新版本是向上兼容的,所以你可以用Flex/Bison来尝试下面的例子。

  Lex

  Lex程序产生一个所谓的‘Lexer’。这是一个将字符流作为它的输入的函数,而且每当出现一组字符串和关键字(key)匹配时,采取一个特定的动作。一个简单的例子为:

Example 2:

%{
#include <stdio.h>
%}

%%
stop    printf("Stop command received\n");
start   printf("Start command received\n");

%%
在第一段,在%{和%}对之间的直接包含在输出程序里。我们需要这么做,因为我们接下来要用printf,它定义在stdio.h里面。接下来的段来以%%分割,所以第二段的第一行以‘stop’键开始,每当‘stop’ key 在输入流中出现是,接下来的行(一个printf() 调用)将会被执行。除‘stop’外,我们还定义了'start',它做的事情差不多一样。我们用“%%”来终结这个代码段。

为了编译这个例子,这样做:
  lex example1.l
cc lex.yy.c -o example1 -ll

NOTE:如果你使用的是flex,则需吧'-ll'改为'-lfl'这项会产生文件'example1',如果你运行它,它会等待你的输入。

正则表达式在匹配过程的使用

Example 2:

%{
#include <stdio.h>
%}

%%
[0123456789]+           printf("NUMBER\n");
[a-zA-Z][a-zA-Z0-9]*    printf("WORD\n");
%%
  多的不说,[0123456789]+ 意为:一串由0123456789组成的一个或多个字符串,我们可以简写为:[0-9]+。[a-zA-Z][a-zA-Z0-9]* 则是说: 第一个字符串必须在'a'~'z'或则'A'~'Z'.换句话说,是一个字母。这个初始化的字符串紧接着是0个或则多个字符串为字母或则数字。‘+’意为者一个或多个,但是一个WORD很可能由一个字符组成。所以第二部分的匹配可能有0个匹配,所以用‘×’。运行的结果为:
$ ./example2
foo
WORD

bar
WORD

123
NUMBER

bar123
WORD

123bar
NUMBER
WORD


一个更复杂类似c语法的例子
 假设我们想要一个如下的例子:
logging {
        category lame-servers { null; };
        category cname { null; };
};

zone "." {
        type hint;
        file "/etc/bind/db.root";
};
 

Example 3:

%{
#include <stdio.h>
%}

%%
[a-zA-Z][a-zA-Z0-9]*    printf("WORD ");
[a-zA-Z0-9\/.-]+        printf("FILENAME ");
\"                      printf("QUOTE ");
\{                      printf("OBRACE ");
\}                      printf("EBRACE ");
;                       printf("SEMICOLON ");
\n                      printf("\n");
[ \t]+                  /* ignore whitespace */;
%%
 
posted @ 2012-08-12 13:56  happydpc  阅读(498)  评论(0编辑  收藏  举报