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

image-20260222210627485

测试指令

 ./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.

image-20260222210913572

输出信息

image-20260222210946326


进阶版本

代码(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.

输出信息

posted @ 2026-02-22 21:17  wilshappy  阅读(8)  评论(0)    收藏  举报