/*
一个字数统计(word_counter)程序,程序读入一个文件然后报告这个文件的行数、单词树和字符数。
*/
%{ // %{ 和 %}之间的代码会被原样照抄到生成的C文件的开头部分。
int chars = 0; // 定义变量,用于计数有多少个字符
int words = 0; // 定义变量,用于计数有多少个单词
int lines = 0; // 定义变量,用于计数有多少行
%}
%% // 这是第二部分,该部分定义一些匹配模式(每个模式必须放在行首)和动作(模式匹配成功是所执行的C代码,使用{}括号括住的一行或多行语句)。
[a-zA-Z]+ {
words++;
chars += strlen(yytext);
} // 当满足正则表达式:[a-zA-Z]+,表示成功识别到了一个单词。words++并且chars增加单词的字符长度
\n {chars++; lines++; } // 当满足正则表达式:\n,表示识别到了换行符。chars++并且lines++
. {chars++; } // 当满足正则表达式:.,表示识别到了任意一个单词。chars++
%% // 这是第三部分,该部分会被拷贝到生成的词法分析器里面的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