随笔 - 51, 文章 - 1, 评论 - 41, 引用 - 0
数据加载中……

用flex写的一个简单代码统计工具

学习编译原理,看完词法分析,对它有了一个大致的了解,便写了下面的例子。这个例子统计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 = 1else 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选项只能统计当前目录下的文件。

posted on 2008-01-01 16:09 lemene 阅读(1194) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理