• Lex入门


    Lex 主要功能是生成一个词法分析器(scanner)的 C 源码,描述规则采用正则表达式(regular expression)。描述词法分析器的文件 *.l 经过lex编译后,生成一个lex.yy.c 的文件,然后由 C 编译器编译生成一个词法分析器。词法分析器,简言之,就是将输入的各种符号,转化成相应的标识符(token),转化后的标识符很容易被后续阶段处理,如YACC 或 Bison,过程如图

    “lex”和“yacc”这两个名字所代表的也包括这些工具的 GNU 版本 flex 和 bison。 给出的代码应该适用于所有主流版本,比如 MKS yacc。它完全是一个融洽的大家族!

    Flex (fast lexical analyser generator) 是 Lex 的另一个替代品。它经常和自由软件 Bison 语法分析器生成器 一起使用。Flex 最初由 Vern Paxson 于 1987 年用C语言写成。Flex手册里对 Flex 描述如下: 

    Flex是一个生成扫描器的工具,能够识别文本中的词法模式。Flex 读入给定的输入文件,如果没有给定文件名的话,则从标准输入读取,从而获得一个关于需要生成的扫描器的描述。此描述叫做 规则,由正则表达式和 C代码对组成。Flex 的输出是一个 C 代码文件——lex.yy.c——其中定义了yylex() 函数。编译输出文件并且和 -lfl 库链接生成一个可执行文件。当运行可执行文件的时候,它分析输入文件,为每一个正则表达式寻找匹配。当发现一个匹配时,它执行与此正则表达式相关的C代码。Flex 不是GNU工程,但是GNU为Flex 写了手册。

    总之,Flex 是词法分析工具,它读取输入源文件,然后生成 C 语言源程序,通常默认的是 "lex.yy.c", 该文件中包含 yylex( ) 例程,并且可以被 C 编译器编译链接为可执行文件,在该词法分析器运行时,它会根据已定义的规则,在遇到一定的匹配模式时执行相应的 C 代码,从而完成词法分析动作

    gcc lex.yy.c 报错:

    In function `yylex':
    lex.yy.c:(.text+0x39b): undefined reference to `yywrap'
    /tmp/ccIx8oEA.o: In function `input':
    lex.yy.c:(.text+0xcdb): undefined reference to `yywrap'

    The scanner calls this function on end of file, so you can point it to another file and continue scanning its contents. If you don't need this, use

    %option noyywrap (一般在文件开头加,类似这样
    %option noyywrap
    %{
    /* * * * * * * * * * * *
     * * * DEFINITIONS * * *
     * * * * * * * * * * * */
    %}
    

     )

    or link with -lfl to use the default yywrap() function in the library fl.(就是gcc lex.yy.c -lfl )

    还有一种办法,我们自己写一个不做什么的yywrap()函数;

    int yywrap()
    {
    	return 1;
    }

    以上3中解决方案都可以。

    输入几行字,计算行数,单词数和字符数.

    %option noyywrap

    %{
    int chars = 0;
    int words = 0;
    int lines = 0;
    %}
    %%
    [a-zA-Z]+  { words++; chars += strlen(yytext); }
    \n         { chars++; lines++; }
    .          { chars++; }
    %%
    main(int argc, char **argv)
    {
      yylex();
      printf("%8d%8d%8d\n", lines, words, chars);
    }
    {}内的是c编写的动作

    按照下面过程编译。

    #flex test.l

    #gcc lex.yy.c  -o main.out

    #./main.out  (不要再这行接着输入文字,flex不会计数的)

    hello world

    you can say

    按ctrl+d结束

    输出结果 2 5 24

    修改上面的例子,将正则表达式放在全局声明中:

    %{
    int chars = 0;
    int words = 0;
    int lines = 0;
    %}
    mywords    [a-zA-Z]+ 
    mylines    \n 
    mychars    .  
    %%
    {mywords}  { words++; chars += strlen(yytext); }
    {mylines}  { chars++; lines++; }
    {mychars}  { chars++; }
    %%
    main(int argc, char **argv)
    {
      yylex();
      printf("%8d%8d%8d\n", lines, words, chars);
    }

    小知识:

    flex有很多选项,我们不想使用默认的lex.yy.c名字,加上

    -o lexname 就可以了。

    flex -o b.yy.c  b.l

    可以使用man flex查看帮助

    The Scanner as Coroutine(协同程序)

    即怎样将扫描到的标记给其他程序使用,下面的例子,希望扫描到+ 或 -时做一个特殊输出。

    当调用yylex时,若扫描到return对应的标记时,yylex返回,且值就为return后的值;

    若没扫描到return对应的标记,yylex继续执行,不返回。

    下次调用自动从前一次的扫描位置处开始。

    %option noyywrap
    %{
    enum yytokentype{
        ADD=259,
        SUB=260
        };
    %}
    
    myadd "+"
    mysub  "-"
    myother .
    
    %%
    {myadd} { return ADD;}
    {mysub} { return SUB;}
    {myother} {printf("Mystery character\n");}
    
    %%
    main(int argc,char **argv)
    {
     int token;
     while(token=yylex())
     {
        if(token==ADD||token==SUB )
        {//yylex的返回值只能是ADD 或 SUB.
          printf("meet + or -\n");
         }
         else {
         printf("this else statement will not be printed, \
                because if yylex return,the retrun value must be ADD or SUB.");
                }
       }
     }

    $./b.out 

    h+f-w
    Mystery character
    meet + or -
    Mystery character
    meet + or -
    Mystery character

    参考:http://www.cnblogs.com/vestinfo/archive/2012/09/29/2708931.html

    http://xiaoxia.org/2011/10/24/writing-a-compiler-learning-gnu-flex-write-a-lexical-analyzer/

    http://web.eecs.utk.edu/~bvz/cs461/notes/flex/

    http://www.ibm.com/developerworks/cn/linux/sdk/lex/

    http://www.ibm.com/developerworks/cn/linux/l-lexyac.html

    http://course.cug.edu.cn/bianyi/shiyan/CHAPTER/f1.htm

     http://wenku.baidu.com/view/5b46758da0116c175f0e4898.html

  • 相关阅读:
    webstorm11.0下载地址和webstorm11.0破解程序patcher.exe下载使用方法说明 前端IDE工具的利器
    20151224今天发现到的两篇关于CSS架构、可复用可维护CSS和CSS学习提升能有改变思想观念意识的文章 分别是CSS架构目标和说说CSS学习中的瓶颈
    GOF提出的23种设计模式是哪些 设计模式有创建形、行为形、结构形三种类别 常用的Javascript中常用设计模式的其中17种 详解设计模式六大原则
    HTML过滤器,用于去除XSS漏洞隐患。
    springboot的快速集成多数据源的启动器
    Springboot根据url后缀返回json或者xml或者html
    Springboot打包成War包并使其可以部署到Tomcat中直接运行
    数据脱敏工具类(包含手机号,银行卡号,邮箱,中文名称等)
    MySQL函数find_in_set介绍
    防止同一IP多次请求攻击
  • 原文地址:https://www.cnblogs.com/youxin/p/3009121.html
Copyright © 2020-2023  润新知