1.01 Flex基本语法格式和规则详解

/* file: 1.01_word_counter.y */
/* 一个字数统计(word_counter)程序,程序读入一个文件然后报告这个文件的行数、单词树和字符数。*/

/* 以下是Flex的第一部分为定义部分,包含选项、文字块、起始条件和转换等。
   文字块存在与%{和%}之间,它们将被原样拷贝到生成文件中。
   以空白字符开头的行会被原样拷贝到C文件中。通常用于/**/之间的多行注释,在每行前面需要有空白字符。
   例如:用于声明选项(%option),以及起始条件start condition(使用%x、%s声明)
   */
%option noyywrap

/* %{ 和 %}之间的代码被认为是文字块,会被原样拷贝到生成的文件的开头部分。*/
%{
int chars = 0; // 定义变量,用于计数有多少个字符
int words = 0; // 定义变量,用于计数有多少个单词
int lines = 0; // 定义变量,用于计数有多少行
%}


/* 以下%%和%%之间是Flex的第二部分为规则部分,该部分定义一些匹配模式(每个模式必须放在行首)和动作(模式匹配成功是所执行的C代码,使用{}括号括住的一行或多行语句)。
   注意:
       在该部分也有%{ 和 %}定义的C代码语句,它们会被原封不动地拷贝到yylex()中。
       在规则部分开头出现的C代码也会出现在yylex的开头,它可以包含词法分析器使用的变量,以及每次yylex()调用时所需运行的代码。
       在其他部分出现的C代码必须仅仅包含注释,因为你无法预知它出现在词法分析器的什么位置。*/
%%
[a-zA-Z]+   {
            words++;
            chars += strlen(yytext); // yytext变量总是指向本次匹配的输入文本字符串
            } // 当满足正则表达式:[a-zA-Z]+,表示成功识别到了一个单词。words++并且chars增加单词的字符长度
\n          {chars++; lines++; } // 当满足正则表达式:\n,表示识别到了换行符。chars++并且lines++
.           {chars++; } // 当满足正则表达式:.,表示识别到了任意一个单词。chars++
%%
/* 以下是Flex的第三部分为用户子例程部分,该部分会被拷贝到生成的词法分析器里面的C代码。
   它们通常是一些与动作相关的程序代码。
   */
int main(int argc, char **argv)
{
    yylex(); // 该函数是词法分析器的主要函数,调用它将进行词法分析
    printf("chars=%8d\n",chars); // 打印有多少个字符
    printf("words=%8d\n",words); // 打印有多少个单词
    printf("lines=%8d\n",lines); // 打印有多少行
    return 0;
}

/*
注意:
    Q:上面的例子可以发现,第三条规则会匹配所有的字符,
    难道它不会也匹配第一个模式所能匹配的单词字母吗?
    A:如果两个模式都匹配的话,flex会选择在程序里面首先出现的那个模式。
*/

如果你使用的是CLion来调试运行以上的代码,你可能会碰到这样的问题:

/home/cmp/work_dir/source_code/yacc_bison_practice/ch1/cmake-build-debug/word_counter
abc
def
^D
input in flex scanner failed

Process finished with exit code 2

正如上面,在CLion中调试运行程序,输入abc换行def换行,然后在输入ctrl+d,程序直接会报错。这是由于CLion使用ctrl+d发送EOF始终有bug。最好在Terminal运行这个程序:
在这里插入图片描述
源码见:
https://github.com/ronnie88597/yacc_bison_practice/blob/master/ch1/word_counter.l

猜你喜欢

转载自blog.csdn.net/weixin_46222091/article/details/105615369
今日推荐