本来应该在4月20日写的,由于种种原因没有写,今天将它补起来.这是正式的按君子抉中的计划来写博客的第二天,今天搞那个垂直搜索搞了一上午,以前还感觉搞这个有点激情,现在感觉完全是一种累赘,还得写文档,麻烦啊.下午才干了点真正有点意思的东西-----flex.
以前从来没有接触过flex,那次听兴旺说要做一个自动的词法分析器,用flex来实现,研究了半天,最后总算明白了.而且今天我才明白原来编程最痛苦的事不是代码怎么写,而是在哪里编写代码.刚开始在网上搜索了半天,都是讲解flex的程序怎么编写,就是没说,写了在哪里进行编译.最后找了半天,明白了.
先下载flex-2.5.4a-1.exe,然后进行安装,我是安装到了D:\GnuWin32,然后在环境变量的path加上一句: ;D:\GnuWin32\bin
再到DOS命令下进行测试安装好了没有,输入 flex -V 即可.这个是大写V.之后就是编写.l文件.编写好.l文件之后,在DOS命令行下定位到你的.l文件的目录,让后输入flex test.l 回车即可.这里test.l是你的.l文件的文件名.让后在test.l文件的同一目录就会生成一个 lex.yy.c.这个文件就可以在Visual Studio中进行编译了.下面这个是我改写的词法分析器的flex的.l文件的代码.
#include < stdio.h >
#include < stdlib.h >
/* 保留字 */
#include < string .h >
char * key[] = { " " , " auto " , " break " , " case " , " char " , " const " , " continue " , " default " , " do " , " double " ,
" else " , " enum " , " extern " , " float " , " for " , " goto " , " if " , " int " , " long " , " register " ,
" return " , " short " , " signed " , " sizeof " , " static " , " struct " , " switch " , " typedef " ,
" union " , " unsigned " , " void " , " volatile " , " while " };
int IsKeyWord( char * lex) ; /* 判断字符串是否是保留字 */
void print(); // 输出token序列;
void main( int argc, char * argv[]); // 主函数;
struct token{ // 二元组;
char * idproperty; // token属性值;
char * idname; // 识别的token名字;
}entity[ 1000 ]; // 定义1000个这样的token,大小可改变;
char * filename; // 保存结果的文件名;
int errnum = 0 ; // 错误token的数目;
int value; // 属性值int型;
int linenum = 1 ; // 行数;
int count = 0 ; // token的个数;
int flag = 0 ;
FILE * fpin; // 测试文件指针;
FILE * fpout; // 结果文件指针;
% }
digit [ 0 - 9 ]
letter [_a - zA - Z]
number {digit} +
identifier {letter}({letter} | {digit}) *
wrongid ({digit} + ){letter}({letter} | {digit}) *
newline [\n]
whitespace [\t] +
allchar [ ^ 0 ] | 0
string_l \ " {allchar}?\ "
%%
{string_l} {value = 6 ;print();} // 字符串常量
{identifier} {value = IsKeyWord(yytext); print();} // 标识符---0 关键字---1
{wrongid} {value = 7 ;print();} // 错误标识符
{number} {value = 2 ;print();} // 数字常量
" ++ " |
" -- " |
" -> " |
" && " |
" || " |
" <= " |
" == " |
" != " |
" >= " |
" >> " |
" << " |
" *= " |
" /= " |
" %= " |
" += " |
" -= " |
" &= " |
" |= " |
" ^= " {value = 4 ;print();} /* 组合运算符 */
" + " |
" - " |
" * " |
" / " |
" ! " |
" % " |
" & " |
" | " {value = 3 ;print();} /* 基本运算符 */
" , " |
" ; " |
" { " |
" } " |
" ( " |
" ) " |
" . " |
" # " |
" ' " {value = 5 ;print();} /* 分界符 */
{newline} {linenum += 1 ;}
{whitespace} {;}
" " {;}
. {value = 7 ;print();} /* 其他不识别 */
%%
int yywrap()
{
fclose(fpin);
return 1 ;
}
void print()
{
count += 1 ;
if (flag != 1 ){
if ((fpout = fopen(filename, " a " )) == NULL){
printf( " 无法打开文件! \n " );
exit( 0 );
}
}
if (value <= 6 ){
switch (value){
case 0 :entity[count - 1 ].idproperty = " 标识符 " ; break ;
case 1 :entity[count - 1 ].idproperty = " 关键字 " ; break ;
case 2 :entity[count - 1 ].idproperty = " 数字常量 " ; break ;
case 3 :entity[count - 1 ].idproperty = " 基本运算符 " ; break ;
case 4 :entity[count - 1 ].idproperty = " 组合运算符 " ; break ;
case 5 :entity[count - 1 ].idproperty = " 分界符 " ; break ;
case 6 :entity[count - 1 ].idproperty = " 字符串常量 " ; break ;
}
entity[count - 1 ].idname = yytext;
fprintf(fpout, " %d < %s , %s > \n " ,count,entity[count - 1 ].idname,entity[count - 1 ].idproperty);
} else {
errnum += 1 ;
switch (value){
case 8 :entity[count - 1 ].idproperty = " 错误标识符: " ; break ;
case 7 :entity[count - 1 ].idproperty = " 不识别: " ; break ;
}
entity[count - 1 ].idname = yytext;
fprintf(fpout, " %d [line:%d]:%s\ " % s\ " \n " ,count,linenum,entity[count - 1 ].idproperty,entity[count - 1 ].idname);
}
if (flag != 1 )fclose(fpout);
}
/* 判断字符串是否是保留字 */
/* 如果不是就返回 0 */
int IsKeyWord( char * lex)
{
int i;
for ( i = 1 ;i <= 32 ;i ++ )
{
if (strcmp(lex,key[i]) == 0 )
return 1 ;
}
return 0 ;
}
void main( int argc, char * argv[])
{
if (argc == 1 ){
printf( " please input the C program(ctrl+z to end) \n " );
flag = 1 ;
fpin = stdin;
fpout = stdout;
}
if (argc == 2 )argv[ 2 ] = " defresult.txt " ;
filename = argv[ 2 ];
if (flag != 1 ){
if ((fpin = fopen(argv[ 1 ], " r " )) == NULL){
printf( " cannot open the file \n " );
exit( 0 );
}
}
yyin = fpin;
yylex();
if (flag != 1 ){
if ((fpout = fopen(filename, " a " )) == NULL){
printf( " cannot write the file \n " );
exit( 0 );
}
}
fprintf(fpout, " \n " );
fprintf(fpout, " %d symbol(s) found. \n %d error(s) found. \n " ,count,errnum);
fprintf(fpout, " ======================================================================= \n " );
if (flag != 1 )fclose(fpout);
yywrap();
}