flex与bison学习之字符统计程序
第一章例子-字数统计
flowchart LR
A([第一章-flex与bison简介])
A-->B[<u>字数统计</u>]
A-->C[英式英语转换为美式英语]
A-->D[一个简单的flex词法分析器]
A-->E[识别计算器的记号]
A-->F[简易计算器]
A-->G[简易计算器_C语言实现词法分析]
classDef highlight fill:gold,font-weight:bold;
class B highlight;
👉字数统计
英式英语转换为美式英语
一个简单的flex词法分析器
识别计算器的记号
简易计算器
简易计算器_C语言实现词法分析
graph LR
A>运用正则表达式来统计各类字符]
代码(001_1_word_count.l)
/* 变量定义 */
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); } /* 匹配26个英文字母,包含大写、小写形式。变量yytext内容为本次匹配的输入文本 */
\n { chars++; lines++; } /* 匹配一个换行符 */
. { chars++; } /* 匹配任意一个字符,除上述两个规则外的其他字符 */
%%
点击展开代码剩余部分
main(int argc, char ** argv)
{
yylex(); /* 调用flex提供的词法分析例程yylex() */
/* 打印统计输出 */
printf("number of lines=%8d\n", lines); /* 行数 */
printf("number of words=%8d\n", words); /* 单词数 */
printf("number of chars=%8d\n", chars); /* 字符数 */
}
说明:
上述程序包含3个部分,各个部分之间同游仅有%%的行来分割。
第1部分:声明和选项设置
第2部分:一系列的模式和动作
第3部分:会被拷贝到词法分析器里面的C代码,他们通常是一些与动作代码相关的例程
Makfile(001_1_word_count.Makefile)
FILE_NAME = 001_1_word_count
FLEX_INPUT_FILE = $(FILE_NAME).l
FLEX_OUTPUT_FILE = $(FILE_NAME).c
FLEX_CMD = flex
FLEX_FLAG = -o
GCC_CMD = gcc
GCC_COMPILE_FLAG = -c
GCC_OUTPUT_FLAG = -o
GCC_LINK_FLAG = -lfl
GCC_OBJECT_FILE = $(FILE_NAME).o
TARGET_FILE = $(FILE_NAME)
点击展开代码剩余部分
all: clean flex_main gcc_main
flex_main: $(FLEX_INPUT_FILE)
$(FLEX_CMD) $(FLEX_FLAG) $(FLEX_OUTPUT_FILE) $(FLEX_INPUT_FILE)
gcc_main: $(FLEX_OUTPUT_FILE)
$(GCC_CMD) $(GCC_COMPILE_FLAG) $(FLEX_OUTPUT_FILE) $(GCC_OUTPUT_FLAG) $(GCC_OBJECT_FILE)
$(GCC_CMD) $(GCC_OBJECT_FILE) $(GCC_LINK_FLAG) $(GCC_OUTPUT_FLAG) $(TARGET_FILE)
.PHONY: clean
clean:
@rm -f $(FLEX_OUTPUT_FILE)
@rm -f $(GCC_OBJECT_FILE)
@rm -f $(TARGET_FILE)
编译指令
make -f 001_1_word_count.Makefile

测试指令
./001_1_word_count
# 输入如下英文句子,按Ctrl+D结束输入
Don't put off till tomorrow what you can do today.
Where there is a will, there is a way.

输出信息

进阶版本
代码(001_1_word_count_plus.l)
/* 变量定义 */
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[^ \t\n\r\f\v]+ { words++; chars += strlen(yytext); } /* 匹配非空白字符 */
\n { chars++; lines++; } /* 匹配一个换行符 */
. { chars++; } /* 匹配任意一个字符,除上述两个规则外的其他字符 */
%%
点击展开代码剩余部分
main(int argc, char ** argv)
{
yylex(); /* 调用flex提供的词法分析例程yylex() */
/* 打印统计输出 */
printf("number of lines=%8d\n", lines); /* 行数 */
printf("number of words=%8d\n", words); /* 单词数 */
printf("number of chars=%8d\n", chars); /* 字符数 */
}
特殊的空白字符表
| 符号 | 含义 | ASCII码值(10进制) | 字符/缩写 |
|---|---|---|---|
| \t | 水平制表符 | 9 | HT/Horizontal Tab |
| \n | 换行符,将光标移动到下一行开始 | 10 | LF(NL)/Line Feed(New Line) |
| \r | 回车符 | 13 | CR/Curriage Return |
| \f | 换页符 | 12 | FF(NP)/Form Page(New Page) |
| \v | 垂直制表符 | 11 | VT(Vertical Tab) |
Makefile(001_1_word_count_plus.Makefile)
FILE_NAME = 001_1_word_count_plus
FLEX_INPUT_FILE = $(FILE_NAME).l
FLEX_OUTPUT_FILE = $(FILE_NAME).c
FLEX_CMD = flex
FLEX_FLAG = -o
GCC_CMD = gcc
GCC_COMPILE_FLAG = -c
GCC_OUTPUT_FLAG = -o
GCC_LINK_FLAG = -lfl
GCC_OBJECT_FILE = $(FILE_NAME).o
TARGET_FILE = $(FILE_NAME)
点击展开代码剩余部分
all: clean flex_main gcc_main
flex_main: $(FLEX_INPUT_FILE)
$(FLEX_CMD) $(FLEX_FLAG) $(FLEX_OUTPUT_FILE) $(FLEX_INPUT_FILE)
gcc_main: $(FLEX_OUTPUT_FILE)
$(GCC_CMD) $(GCC_COMPILE_FLAG) $(FLEX_OUTPUT_FILE) $(GCC_OUTPUT_FLAG) $(GCC_OBJECT_FILE)
$(GCC_CMD) $(GCC_OBJECT_FILE) $(GCC_LINK_FLAG) $(GCC_OUTPUT_FLAG) $(TARGET_FILE)
.PHONY: clean
clean:
@rm -f $(FLEX_OUTPUT_FILE)
@rm -f $(GCC_OBJECT_FILE)
@rm -f $(TARGET_FILE)
编译指令
make -f 001_1_word_count_plus.Makefile

测试指令
./001_1_word_count_plus
# 输入如下英文句子,按Ctrl+D结束输入
Don't put off till tomorrow what you can do today.
Where there is a will, there is a way.

输出信息


浙公网安备 33010602011771号