您的位置:首页 > 其它

词法分析器 (SNL语言) 自己写的,拿出来大家一起分享,指正

2008-03-24 12:51 435 查看
自己实验课写的一个词法分析程序,针对SNL语言的,有兴趣的看一下,单文件,可能不是很清晰,先对付看吧,有时间我再把他改一下

#include<stdio.h>
#include<string.h>
#include <stdlib.h>

/**********************类型定义*************************/
/*标识符(BSF) 1 -------常量(CL) 2---------- 分符隔(FJF)3------ 保留字(BLZ) 10 ------------*/
/*错误 (CW) 100-----双分界符:=(SFJF)4------程序结束标志(CXJS)6------数组下表(SZXB)7------*/
/**************************************************************/
struct TOKEN //token序列结构
{
int line; //行号
char str[20]; //用来存字符串本身
int type; //存储类型
};
const int maxnum_que=30; //定义队列最多容纳字符
struct queue
{
void insert(char ch); //向队列尾插入一个字符
void ini(); //队列初始化函数
void delet(); //删除队列头元素
char view_head(); //查看队列头元素
bool empty(); //判断队列是否为空
void clear(); //清空队列
int count; //对里元素计数
int rear; //队尾
int head; //对头
char a[maxnum_que];
};
bool lookup(char* str); //查找是否是保留字
void insert_token(int line,int stat,queue store,TOKEN token[],int count,int p_token);
void send_error(int line,char ch); //发送错误消息
void getTokenlist();
//****************************************************************************************************
const int baol_n=21;
char * baoliuzi[baol_n]={"char","int","var","program","integer","procedure","array","begin","while","if",
"then","else","endwh","end","read","of","record","fi","return","write","type"}; //个数未必是二十,查找时注意????????????????????????没完
bool lookup(char* str) //查找是否是保留字
{
int i;
bool m=false;
for(i=0;i<baol_n;i++)
{
if(strcmp(str,baoliuzi[i])==0)
{
m=true;
break;
}
}
return m;
}
//////////////////////////////////////queue 结构里的函数声明///////////////////////////////////////
void queue::clear()
{
count=head=rear=0;
}
void queue::ini()
{
count=head=rear=0;
}
void queue::delet()
{
if(count<=0)
printf("队列里已经没有字符可以删除!!!!!!!!!!!!!!/n");
else
{
head++;
if(head>=maxnum_que)
head=head%maxnum_que;
count--;
}
}
char queue::view_head()
{
if(count>0)
return a[head];
else
printf("没有字符可以查看!!!!!!!!!!!/n");
}
bool queue::empty()
{
if(count<=0)
return true;
else
return false;
}
void queue::insert(char ch)
{
if(count>=maxnum_que)
printf("队列已满 缓冲区溢出!!!!!!!!!!!!!!!!!!!/n");
else
{
a[rear]=ch;
rear++;
if(rear>=maxnum_que)
rear=rear%maxnum_que;

count++;
}
}
///*******************************************************************************************//
void insert_token(int line,int stat,queue store,TOKEN token[],int count,int p_token,int type)
{
token[p_token].line=line;
switch(stat)
{
case 1:
token[p_token].type=1;
break;
case 2:
token[p_token].type=2;
break;
case 3:
token[p_token].type=3;
break;
case 5:
token[p_token].type=4;
break;
case 6:
token[p_token].type=5;
break;
case 7:
token[p_token].type=6;
break;
case 8:
token[p_token].type=7;
break;
}
int q,m;
for(int i=0;i<count;i++)
{
q=store.head;
m=q+i;
if(m>=maxnum_que)
m%=maxnum_que;
token[p_token].str[i]=store.a[m];
}
token[p_token].str[i]='/0';
token[p_token].type=type;
if(type==1)
{
if(lookup(token[p_token].str))
token[p_token].type=10;
}
}
//**************************************************************************************************
void getTokenlist() //获取token 序列
{
char ch; //用来读取字符
int line; //记录当前行数
int stat; //标志状态
line=1; //初始在第一行
stat=0; //初始状态
TOKEN token[3000]; //长度为10000的结构数组
int p_token; //标志着token存到第几个
p_token=0;
FILE * fp;
if((fp=fopen("source.txt","r"))==NULL)
printf("打开文件出错 !!!!!!!!!!!!/n");

queue linshi,store; //声明两个队列
linshi.ini();
store.ini();
ch=fgetc(fp);
//printf("%c",ch);

linshi.insert(ch);
int type;
while(stat!=14)
{
if(stat!=0)
{
char temp;
temp=linshi.view_head();
switch (stat) // 队列操作,给出下一个状态 还是原来的状态则取新的,删除旧的,否则只改变状态
{
case 1:
if(((temp>='A'&&temp<='Z')||(temp>='a'&&temp<='z'))||(temp>='0'&&temp<='9'))//还是标示符
{
store.insert(temp);
//printf("count=%d/n",store.count);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else //不是标示附
{
stat=13; //转到结束状态
type=1;
}
break;
case 2:
if(temp>='0'&&temp<='9') //还是数字
{
store.insert(temp);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else //不是数字,转到结束状态
{
stat=13;
type=2;
}
break;
case 3:
stat=13;
type=3;
break;
case 4:
if(temp=='=')
{
stat=5;
store.insert(temp);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else
{
send_error(line,temp);
stat=13;
type=100; //错误状态
}
break;
case 5:
stat=13;
type=4;
break;
case 6:
if(temp!='}')
{
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);
if(ch=='/n')
line++;
linshi.insert(ch);
}
else
stat=14;
}
else
{
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
stat=13;
}
break;
case 7:
if(temp=='.')
{
stat=8;
store.insert(temp);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else
{
stat=13; ///////////////////程序结束标志
type=6;
}
break;
case 8:
stat=13;
type=7;
break;
}
}
if(stat==0) //如果是s0的话则表明重新开始读 要给出下一个状态
{
char c=linshi.view_head();
if((c>='A'&&c<='Z')||(c>='a'&&c<='z'))// 说明是标示附
{
stat=1;
store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else if(c>='0'&&c<='9')//说明是数字
{
stat=2;
store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c==';'||c=='['||c==']'||c=='='||c=='<')
{
stat=3;
store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else if(c==' '||c=='/n'||c=='/t')
{
if(ch=='/n')
line++;
stat=13;
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;
}
else if(c==':')
{
stat=4;
store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);

}
else
stat=14;
}
else if(c=='{')
{
stat=6;
//store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);
linshi.insert(ch);
}
else
stat=14;
}
else if(c=='.')
{
stat=7;
store.insert(c);
linshi.delet();
ch=fgetc(fp);
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
{
stat=14;

}
}
else //其它的类似逗号之类的错误
{
send_error(line,c);
linshi.delet();
ch=fgetc(fp);
stat=13;
if(ch!=EOF)
{
//printf("%c",ch);

linshi.insert(ch);
}
else
stat=14;

}
}
if(stat==13)
{
if(!store.empty())
{
insert_token(line,stat,store,token,store.count,p_token,type);

p_token++;

}
store.clear();
stat=0;
}
if(stat==14)
{
if(!store.empty())
{
insert_token(line,stat,store,token,store.count,p_token,type);
store.clear();
p_token++;
//break;
}
}
}
if(fclose(fp)==EOF)
printf("关闭文件出错 !!!!!!!!!!! /n");

FILE *fpp=fopen("token.txt","w");

/*printf("/******************************类型定义********************************/n"); //屏幕输出
printf("/*标识符1-----常量2------分符隔3------保留字10-------错误 100------/n");
printf("双分界符:=4-----注释头符号5-----程序结束标志6------数组下表7------*/n");
printf("/********************************************************************/n");
printf("行号 类型 字符串/n");
for(int j=0;j<p_token;j++)
printf("%d %d %s /n",token[j].line,token[j].type,token[j].str);*/
fprintf(fpp,"/******************************类型定义********************************//n");
fprintf(fpp,"/*标识符1-----常量2------分符隔3------保留字10-------错误 100-------/n");
fprintf(fpp,"双分界符:=4-----注释头符号5-----程序结束标志6------数组下表7------*//n");
fprintf(fpp,"/********************************************************************//n");
fprintf(fpp,"行号 类型 字符串/n");
for(int p=0;p<p_token;p++)
fprintf(fpp,"%d %d %s /n",token[p].line,token[p].type,token[p].str);
}
void send_error(int line,char ch)
{
printf("在 第 %d 行 字符 %c 有错误!!!!!!!!!!!!!!!!!!!!!!!!!!!/n",line,ch);
}

//****************************************************************************************************
void main()
{
getTokenlist();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐