学习编译原理,看完词法分析,对它有了一个大致的了解,便写了下面的例子。这个例子统计C或C++代码中有多少行注释,多少行代码。实现简单,但功能还不错。
这里用到了正则表达式,flex的用法,windows批处理的编程知识。
stat.c文件:实现对一个文件进行统计。
/* stat.c */
%option noyywrap
%{
#include <stdio.h>
/* 一行内既有代码又有注释, 则codeno,commentno都加一 */
int lineno = 0; /* 总行数 */
int emptylineno = 0; /* 空行数 */
int codeno = 0; /* 代码行数 */
int commentno = 0; /* 注释行数 */
int is_comment = 0; /* 该行是否为注释 */
int in_comment = 0; /* 是否在注释内,主要考虑跨行的注释代码 */
int is_code = 0; /* 该行是否为代码 */
%}
%%
\/\/ { is_comment = 1; } /* 匹配以//开始的注释 */
\/\* { in_comment = 1; is_comment = 1; } /* 匹配另一种注释 */
\*\/ { in_comment = 0; is_comment = 1; }
[^ \t\n] { if (in_comment) is_comment = 1; else is_code = 1; } /* 非空格字符 */
\n { /* 一行结束了,分析这行的属性 */
lineno++;
if (!is_comment && !is_code)
emptylineno++;
else
{
if (is_comment)
commentno++;
if (is_code)
codeno++;
}
is_comment = 0;
is_code = 0;
}
. { ; } /* 匹配漏掉的字符,使它不输出 */
%%
int main()
{
yylex();
/* 匹配最后一行 */
if (is_comment)
{
lineno++;
commentno++;
}
else if (is_code)
{
lineno++;
codeno++;
}
printf("%d\t%d\t%d\t%d\n", lineno, emptylineno, commentno, codeno);
return 0;
}
编译
D:\Work\lex>flex stat.c
D:\Work\lex>gcc -o statfile.exe lex.yy.c
D:\Work\lex>statfile < stat.c
46 3 15 39
这只是统计一个文件的程序,利用批处理实现统计当前目录包括子目录下的所有的*.c,*.cpp,*.h文件。
1 使用for /r %%a in (*.c *.h *.cpp) do @a.exe < %%a >>__tmp__.txt 命令枚举所有文件,把统计结输入到__tmp__.txt中。
2 使用add.exe把__tmp__.txt数据相加。
3 删除__tmp__.txt文件。
add.c文件:
/* add.c */
#include<stdio.h>
int main()
{
int recv[4] ;
int res[4] = {0,0,0,0};
int i;
while (1)
{
/* 读取数据 */
if(scanf("%d\t%d\t%d\t%d", recv,recv+1,recv+2,recv+3)==EOF)
break;
for (i=0; i<4; i++)
res[i] += recv[i]; /* 数据相加 */
}
/* 输出结果 */
printf("%d\t%d\t%d\t%d", res[0], res[1], res[2], res[3]);
return 0;
}
编译 gcc -o add.exe add.c
stat.bat文件:
@rem stat.bat
@echo off
if "%1" == "-f" goto file rem 统计单个文件
if "%1" == "-h" goto help rem 帮助信息
if "%1" == "-d" goto dir rem 统计当前目录下的文件
:dir
for /r %%a in (*.c *.h *.cpp) do @statfile.exe < %%a >>__tmp__.txt
echo All Blank Comment Code
add.exe < __tmp__.txt
del __tmp__.txt
goto exit
:help
echo usage: [-dfh][filename]
echo -d 统计当前目录和子目录所有的文件的代码注释
echo -f filename 统计该文件代码注释
echo -h 帮助
goto exit
:file
echo All Blank Comment Code
statfile.exe < %2
goto :exit
:exit
echo on
现在可以运行stat.bat
D:\Work\lex>stat -h
usage: [-dfh][filename]
-d 统计当前目录和子目录所有的文件的代码注释
-f filename 统计该文件代码注释
-h 帮助
D:\Work\lex>stat -f stat.c
All Blank Comment Code
46 3 15 39
D:\Work\lex>stat -d
All Blank Comment Code
3026 580 547 1978
这个程序有一缺点,-d选项只能统计当前目录下的文件。