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

用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  =   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选项只能统计当前目录下的文件。

你可能感兴趣的:(用flex写的一个简单代码统计工具)