本来应该在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();
}
#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();
}