📄 词法分析.txt
字号:
查看文章
编译原理词法分析程序(C语言)2008年05月09日 星期五 22:03/*头文件pl0.h*/
#define al 10/*符号的最大长度*/
#define nmax 14/*number的最大位数*/
#define norw 8/*关键字个数*/
char ch;/*获取字符的缓冲区,getch使用*/
int cc,ll;/*cc表示当前字符(ch)的位置*/
char line[81];/*读取行缓冲区*/
char a[al+1];/*临时符号,多处的字节用于存放0*/
char anum[nmax+1];/*临时符号,存放number*/
char inum[nmax+1];/*存放常数*/
char word[norw][al];/*保留字*/
char fname[al];/*文件名*/
char id[al+1];/*存放标识符或保留字*/
int num;/*常数*/
int err;//错误计数器
FILE * fin;
FILE * fout;
FILE * fas;/*词法分析结果文件*/
/*函数执行出错,退出程序*/
#define getchdo if(-1==getch()) return -1
#define getsymdo if(-1==getsym()) return -1
int getch();/*读取一行字符*/
int getsym();/*读取一个分词*/
/*主程序*/
/*
*运行环境:Microsoft visual c++ 6.0
*/
/*
*程序功能要求:
*编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,
*即基本保留字、标识符、常数、运算符、界符五大类。并依次输出各个单词的内部编码及单词符号自身值。
*单词的内部编码如下:
*1.保留字:if、int、for、while、do、return、break、continue;单词种别码为1;
*2.标识符:除保留字外的以字母开头,后跟字母、数字的字符序列;单词种别码为2;
*3.常数为无符号整形数;单词种别码为3;
*4.运算符包括:+、-、*、/、=;单词种别码为4;
*5.分隔符包括:,、;、{、}、(、); 单词种别码为5。
*/
/*
*各类单词的文法
*<标识符>→<字母><字母数字串>
*<字母数字串>→<字母><字母数字串>|<数字><字母数字串>|ε
*<无符号整数>→<数字>|<数字><无符号整数>
*<运算符>→ + | - | * | / | =
*<界符>→ , | ; | ( | ) | { | }
*/
/*
*程序输出格式(<单词种别码>,"<单词符号>")
*例如对于源程序
main()
{
int a, b;
a = 10;
b = a + 20;
}
输出格式为
(2,"main")
(5,"(")
(5,")")
(5,"{")
(1,"int")
(2,"a")
(5,",")
(2,"b")
(5,";")
(2,"a")
(4,"=")
(3,"10")
(5,";")
(2,"b")
(4,"=")
(2,"a")
(4,"+")
(3,"20")
(5,";")
(5,"}")
*/
#include<stdio.h>
#include<string.h>
#include"pl0.h"
/*从文件fin中读取一行字符,保存到字符缓冲区line中*/
int getch()
{
if(cc==ll)
{
if(feof(fin))
{
printf("program incomplete");
return -1;
}
ll=0;
cc=0;
ch=' ';
while(ch!=10)
{
if(EOF==fscanf(fin,"%c",&ch))
{
line[ll]=0;
break;
}
line[ll]=ch;
ll++;
}
}
ch=line[cc];
cc++;
return 0;
}
/*读取一个分词*/
int getsym()
{
int i,j,k;
while(ch==' '||ch==10||ch==9)//忽略空格,换行和TAB
{
getchdo;
}
if(ch>='a'&&ch<='z')//判断是否为关键字或标识符
{
k=0;
do{
if(k<al){
a[k]=ch;
k++;
}
getchdo;
}while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');
a[k]=0;
if(k>al)printf("error");
strcpy(id,a);
i=0;
j=norw-1;
do{
k=(i+j)/2;
if(strcmp(id,word[k])<=0)
{j=k-1;
}
if(strcmp(id,word[k])>=0)
{
i=k+1;
}
}while(i<=j);
if(i-1>j)
{
fprintf(fas,"(1,\"%s\")\n",id);/*分词为关键字*/
}
else {
fprintf(fas,"(2,\"%s\")\n",id);/*标识符*/
}
}
else if(ch>='0'&&ch<='9')/*判断分词是否为常数*/
{
k=0;
num=0;
do{
num=10*num+ch-'0';
anum[k]=ch;
k++;
getchdo;
}while(ch>='0'&&ch<='9');
fprintf(fas,"(3,\"%d\") ",num);/*常数*/
anum[k]=0;
if(k>nmax)/*常数位数超过规定的最大位数,报错*/
{ strcpy(inum,anum);
fprintf(fas,"常数%s超出范围!",inum);
}
fprintf(fas,"\n");
}
else if(ch=='+')/*运算符*/
{ fprintf(fas,"(4,\"%c\")\n",ch);
getchdo;
}
else if(ch=='-')
{
fprintf(fas,"(4,\"%c\")\n",ch);
getchdo;
}
else if(ch=='*')
{ fprintf(fas,"(4,\"%c\")\n",ch);
getchdo;
}
else if(ch=='/')
{
fprintf(fas,"(4,\"%c\")\n",ch);
getchdo;
}
else if(ch=='=')
{ fprintf(fas,"(4,\"%c\")\n",ch);
getchdo;
}
else if(ch==',')/*界符*/
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else if(ch==';')
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else if(ch=='{')
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else if(ch=='}')
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else if(ch=='(')
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else if(ch==')')
{
fprintf(fas,"(5,\"%c\")\n",ch);
getchdo;
}
else{/*其他字符*/
getchdo;
}
return 0;
}
void init()/*初始化*/
{
/*设置保留字名字,按照字母顺序,便于折半查找*/
strcpy(&(word[0][0]),"break");
strcpy(&(word[1][0]),"continue");
strcpy(&(word[2][0]),"do");
strcpy(&(word[3][0]),"for");
strcpy(&(word[4][0]),"if");
strcpy(&(word[5][0]),"int");
strcpy(&(word[6][0]),"return");
strcpy(&(word[7][0]),"while");
}
int main()
{
printf("请输入源文件名:");
scanf("%s",fname);
fin=fopen(fname,"r");
if(fin)
{
fas=fopen("fas.txt","w");
init();
err=0;
cc=ll=0;
ch=' ';
do{
getsymdo;
}while(!feof(fin));
fclose(fas);
fclose(fin);
}
else{
printf("can't open file!");
}
printf("词法分析结果已保存到文件fas.txt\n");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -