flex词法分析器简介

        flex和bison是用来生成程序的工具,它们生成的程序能够处理结构化输入。起初它们被设计用来作为编译器的一部分进行词法和语法分析,但是后来证明它们在其他领域也十分有效,因此并不是只有学习编译原理的同学需要学习它们,使用c语言的同学都可以学习并使用它们,下面我先简单介绍flex词法分析器。(注意,我介绍的flex并不是指adobe flex)

        简单来说,词法分析器把输入分割成一个个有意义的词块,成为记号(token),而语法分析则是确定这些记号是如何彼此关联的,例如下面的一个C片段:

alpha = beta + gamma;

        词法分析器把代码分解为这样一系列记号:alpha,'=',beta,'+',gamma,';'。接着语法分析器确定bate+gamma是一个表达式,表达式的值被赋给了alpha。

        flex语法分为3个部分,定义段,规则段,用户代码段,下面是一个简单例子:

/*类似unix的wc程序 fb1-1.l*/
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[a-zA-Z]+    {words++; chars+=strlen(yytext);}
\n           {chars++; linus++;}
.            {chars++;}
%%

main(int argc, char **argv)
{
    yylex();
    printf("%8d%8d%8d\n",line, words, chars);
}

        这个程序大部分内容对C程序员来说都是熟悉的,因为大部分都是C代码,其中%%把代码分成了三部分,第一个部分包含声明和选项设置,第二个部分是一系列的模式和动作,第三部分是会被拷贝到生成的词法分析器里的C代码,它们通常是一些与动作代码相关的例程。

        在声明部分,%{和%}之间的代码会被原样抄到生成的C文件开头部分,在这例子里声明了行数、单词数和字符数的变量。

        第二部分,每个模式处在一行的开头处,接着是模式匹配时所需执行的C代码,这儿的C代码是用{}括住的一行或多行语句(flex认为空白开始的行都是代码而把他们照抄到生成的C程序中。模式在出现空白字符处结束)

        这个程序一共有三个模式,第一个,[a-zA-Z]+,用来匹配一个单词。这是一个正则表达式,如果要使用字母原来的意思,则需要用双引号包裹,如“.”代表点,而不是任意字符;第二个模式,\n,用来匹配换行符。相关动作更新行数和字符数。最后模式是一个点好,代表任意一个字符。

        末尾的C代码是我们的主程序,它负责调用flex的词法分析例程yylex(),并输出结果。在没有任何其他设置的情况下,词法分析器默认读取标准输入。接着就是编译和运行了。

$flex fb1-1.l
$gcc lex.yy.c -lfl -o wc
$./wc

        输入Ctrl-D结束输入,就能获得输入的行数,单词数和字符数。

        我们使用flex来翻译我们的程序,flex在没有任何错误的情况下默默完成了翻译,正如UNIX的经典设定那样。接着我们编译flex生成的C程序: lex.yy.c;将它与相应的flex库文件(-lfl)链接;运行它;然后提供一小段输入进行统计计算。看起来一切运行正常。

        怎么样,一个wc程序,如果光用C语言实现需要很多代码,而使用了flex则只需几行,而且思路清晰,错误检查也很容易。这就是flex的魅力,感兴趣的同学想要更深入的学习flex的话,推荐flex&bison这本书,本文很多都摘自这本书。

        flex编译fb1-1.l后生成的lex.yy.c中的代码有2000行左右,因此就不贴出来分析了^_^。

        这次先简单介绍到这里,下次带来更加详细的flex程序讲解。

你可能感兴趣的:(linux,Flex,C语言,wc,词法分析器)