Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134369
  • 博文数量: 51
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 540
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-21 12:33
文章分类

全部博文(51)

文章存档

2011年(1)

2010年(5)

2009年(1)

2008年(12)

2007年(32)

我的朋友

分类:

2007-08-09 20:01:50

1. lex介绍
 
Lex 代表 Lexical Analyzar, 是一种生成词法分析器的工具.
当 Lex 接收到文件或文本形式的输入时,它试图将文本与正则表达式进行匹配。
如果能够找到一个匹配的模式,Lex 就执行相关的动作(可能包括返回一个标记)。
另一方面,如果没有可以匹配的正则表达式,将会停止进一步的处理,
Lex 将显示一个错误消息.
 
2. lex程序的格式
 
... definitions ...
%%
... rules ...
%%
... subroutines ...
 
3. lex的正则表达式
 
.  匹配任意字符,除了 \n。
-  用来指定范围。例如:A-Z 指从 A 到 Z 之间的所有字符。
[ ]  一个字符集合。匹配括号内的 任意 字符。如果第一个字符是 ^ 那么它表示否定模式。
     例如: [abC] 匹配 a, b, 和 C中的任何一个。
* 匹配 0个或者多个上述的模式。
+ 匹配 1个或者多个上述模式。
? 匹配 0个或1个上述模式。
$ 作为模式的最后一个字符匹配一行的结尾。
{ } 指出一个模式可能出现的次数。 例如: A{1,3} 表示 A 可能出现1次或3次。
\ 用来转义元字符。同样用来覆盖字符在此表中定义的特殊意义,只取字符的本意。
^ 否定。
| 表达式间的逻辑或。
"<一些符号>" 字符的字面含义。元字符具有。
/ 向前匹配。如果在匹配的模版中的"/"后跟有后续表达式,只匹配模版中"/"前面的部分。
   如:如果输入 A01,那么在模版 A0/1 中的 A0 是匹配的。
( ) 将一系列常规表达式分组。
例子:
abc可以匹配abc
abc*可以匹配ab, abc, abcc, abccc, …
abc+可以匹配abc, abcc, abccc, …
a(bc)+可以匹配abc, abcbc, abcbcbc, …
a(bc)?可以匹配a, abc
[abc]可以匹配a, b, c
[a-z]可以匹配任何a到z之间的字符
[a\-z]可以匹配a, -, z
[-az]可以匹配-, a, z
[A-Za-z0-9]+可以匹配一个或多个字符串
[ \t\n]+可以匹配空格, tab和换行
[^ab]可以匹配除去a和b之外的任何字符
[a^b]可以匹配a, ^, b
[a|b]可以匹配a, |, b
a|b 可以匹配a 或者 b
 
4. lex编译
 
   (1). 使用lex将lex文本编译为c文件.
        For GNU lex编译器: Flex
        flex name.l
        lex.yy.c将会产生. 也可以指定
        生成文件的名字
    (2). 将生成的c源文件编译为可执行文件
        
       For GNU GCC编译器: gcc
       gcc -o test lex.yy.c
       将会生成文件名为test的可执行文件.
 
5. 使用lex实现统计c源文件中非注释的行数(ncsl: non-comment source lines)
 
 

%{
/*
 * count the non-comment lines in a file.
 * Author: Gavin Xu
 */

int ncsl_lines, comment_lines, macro_lines;

%}
opencom \/\*
closcom \*\/
%start COMMENT
%start P
%%
    int start=1;
    BEGIN P;
{opencom}    { BEGIN COMMENT; }
<COMMENT>. { }
<COMMENT>\n { comment_lines++; }
<COMMENT>{closcom}    { BEGIN P; }
<P>switch.*;    { ncsl_lines++; }
<P>switch.*\n    { ncsl_lines++; }
<P>for.*;    { ncsl_lines++; }
<P>for.*\n    { ncsl_lines++; }
<P>if.*;    { ncsl_lines++; }
<P>if.*\n    { ncsl_lines++; }
<P>[ \t]*else[ \t]*\n {}
<P>while.*;    { ncsl_lines++; }
<P>while.*\n    { ncsl_lines++; }
<P>case.*[0-9a-zA-Z_]+.*: |
<P>default[ \t]*:    { ncsl_lines++; }
<P>[ \t]*\{[ \t]*\n    { }
<P>[ \t]*\}[ \t]*\n    { }
<P>.*[0-9a-zA-Z_]+.*;\n { ncsl_lines++; }
<P>\/\/.*\n { comment_lines++;}
<P>[ \t]*[0-9a-zA-Z_]+\(.*\).*\n { }
<P>^#define.*\n { macro_lines++;}
<P>^#include.*\n { macro_lines++; }
<P>^#ifdef.*\n { macro_lines++; }
<P>^#ifndef.*\n { macro_lines++; }
<P>^#else.*\n { }
<P>^#endif.*\n { }
<P>. { }
\n
%%

main(argc,argv)
int argc;
char *argv[];
{

     ncsl_lines = 0;
     comment_lines = 0;
     macro_lines = 0;
    

     ++argv, --argc; /* skip over program name */
     if ( argc > 0 )
     {
          yyin = fopen( argv[0], "r" );
         if ( !yyin ) return -1;
        
     }
     else
          yyin = stdin;


     yylex();

     printf("\ncounting ncsl lines of file: %s: \n",argv[0]);
        
     printf("comment lines: %d\n", comment_lines);
     printf("ncsl lines: %d\n", ncsl_lines);
     printf("macro lines: %d\n", macro_lines);
     printf("\n");
     
}

阅读(2867) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~