• [转载]Flex的文件规则


    原文在:https://blog.csdn.net/hczhiyue/article/details/20483209

    文章中给的一个定义很明白,对于初学者来说很有帮助:

    什么是 FLEX?它是一个自动化工具,可以按照定义好的规则自动生成一个 C 函数 yylex(),也成为扫描器(Scanner)。这个 C 函数把文本串作为输入,按照定义好的规则分析文本串中的字符,找到符合规则的一些字符序列后,就执行在规则中定义好的动作(Action)。

    Flex 文件就是一个文本文件,内容包括定义好的一系列词法规则。文件的命名习惯上以小写字母 l(L) 来作为文件后缀。如果为了清晰,也可以用. flx 或者. flex 作为文件的后缀名。

    有几个很重要的地方,之前自己在做的时候没有注意过,特别是关于语言的格式(缩进等):

    1. 如果在 Flex 文件中没有提供 main() 函数的定义,那么这个 C 文件中不会有 main() 函数。此时单独编译这个 C 文件的时候,一定要加上 - lfl 的连接库参数;若提供了 main() 函数,就不必要提供这个连接库参数了。连接库 libfl 提供了一个缺省的 main 函数。缺省的 main() 函数中只是简单地调用 yyflex() 函数,而自己提供的 main() 函数则可以根据需要加入许多其他的处理代码。
    2. 规则由模式 (pattern) 和动作 (action) 两个部分组成。模式就是一个正则表达式,FLEX 加入了一些自己的扩展。而动作一般就是一些 C 语句。模式指出了一个单词是如何构成的,当分析出一个符合该规则的单词时,就执行相应的动作。
      模式一定要位于一行的开头处,不能有缩进。动作的开头一定要与模式在同一行当动作是用一对花括号 {} 括起来时,可以将左花括号放在与规则相同的行,而其余部分则可以从下一行开始。
    3. 所有用户代码都被原样拷贝到文件 lex.yy.c 中。
    4. 在定义段或者规则段中,任何一行有缩进的文本或者包含在一对 %{和 %} 之间(在书写时 %{和 %} 都必须在一行的开始处,不能缩进。)的文本,都被原样拷贝到最后生成的 C 代码文件中(当然 %{和 %} 会被移走)。
    5. 在规则段中,第一条规则之前的任何未缩进的文本或者在 %{和 %} 之间的文本,可以用来为扫描器声明一些本地变量和代码(由上一条可知,他们是会进入C代码文件中的)。一旦进入扫描器的代码,这些代码就会被执行。规则段内其他的缩进的文本或者 %{和 %} 之间的文本还是被原样拷贝输出,但是他们的含义是尚未有明确定义,很可能引起编译时(compile-time)错误
    6. 在定义段中,没有缩进的注释也会被原样拷贝到最后生成的 C 代码文件中,例如以 /* 开始的一行注释,直到遇到 */,这中间的文本会被原样拷贝输出。

    除此之外,当初我在学习时写了一个示例程序,用来帮助理解flex文件格式:

     1 %{
     2 #include <stdio.h>
     3 int nchar, nword, nline; /*声明部分,确定要包括的库文件,以及要声明的变量,这部分将来会直接翻译到c文件中*/
     4 %}/*辅助定义部分,辅助定义部分可包含:正规式的辅助定义(内部使用、不与输入进行匹配)、入口定义、LEX选项等.*/
     5 %option yylineno /*yylineno可以提供当前的行数信息,是Lex内置的变量之一*/
     6 TYPEID          [A-Z]+[_A-Za-z0-9]*
     7 OBJECTID        [a-z]+[_a-zA-Z0-9]*
     8 
     9 STR_CONST           ".*"
    10 INT_CONST       [0-9]+
    11 
    12 WHITE           [ 	]+
    13 LINE            
    
    14 
    15 %s              MutiCom/*多重入口的声明,存放在辅助定义中,以关键字%start或%x开始,其后可以跟若干个被声明的入口,如:%start entry1 entry2 ...(特点:与0入口不互斥)*/
    16 %% 
    17  /*翻译规则部分
    18  *注释不能顶格写*/
    19 [ 	]                  /* 匹配到一个空格或Tab键,不反映 */
    20 
             {nline++; }  /* 匹配到一个换行符,行数加1 */
    21 [^ 	
    ]+  {
    22              /* 匹配到一个不包括空格、Tab键和换行符的字,
    23                 字数加1,字符数加yyleng(字符长度) */
    24              nchar+=yyleng;
    25          nword++;
    26             }
    27 
    28 %%
    29  /*用户自定义程序部分*/
    30 int main()
    31 { 
    32    printf("Press CTRL+d to quit.
    Input any text:
    ");
    33    yylex();             /* 调用词法分析器,直到输入结束  */
    34    printf("nchar=%d, nword=%d, nline=%d
    ", nchar, nword, nline);
    35    return 0;
    36 }
    37 
    38 /* 函数yywrap是LEX提供的一个库函数
    39  * 若生成可执行程序时没有链接LEX库,则必须手工定义
    40  * 反之,生成可执行程序时必须如此:
    41  * cc -o a.out lex.yy.c -ll    # for LEX
    42  * cc -o a.out lex.yy.c -lfl   # for FLEX
    43  * 其中-ll表示连接函数库libl.a(in UNIX)
    44  */
    45 // int yywrap(){ return 1; }
  • 相关阅读:
    退出窗口时出现“当”的响声
    屏幕设备环境
    修改一个完全颜色的CListCtrl类
    修改一个完全颜色的CListCtrl类
    MFC中CString.Format的详细用法
    网上阅卷系统自动识别功能代码
    mfc 子对话框数据传给父对话框
    already defined in *.obj
    Object 的使用
    this 函数执行上下文
  • 原文地址:https://www.cnblogs.com/jiading/p/10793029.html
Copyright © 2020-2023  润新知