⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 accidenceanalysis.cpp

📁 使用循环分支方法实现PL/0语言的词法分析器
💻 CPP
字号:
/* =========================================================================== *\
   Author   :   skyang
   Date     :   11 - 23 - 2007

   Description: Accidence Analysis,which is used to analyse a subset of PASCAL(PL/0),
				input the source code in a file named "test.in" and output the words and 
				their properties in	a file named "res.out", besides, this software also
				indicate the position of accidence error in the source file.
				The size of source code can't be larger than 100000 words.

   Warning :    Copyright (c) skyang 2007 All rights reserved.
\* =========================================================================== */


#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define N 100000

char ch;	//单个字符缓冲
char strToken[128];//字符串缓冲区,标识符不得超过127个字符
struct{
   int flag;//1表示符号串在key表中;0表示符号串是标识符,在idList中;-1表示符号串是整数,在intList中
   int id;//表示在不同表中的下标
}Word[N];	//记录源程序单词符号串及其属性码

int idListlen,intListLen;//标识符表和常数表的长度
char idList[N][128];//标识符表
int intList[N];//常数表
int error;//记录错误个数
int row;//记录行号,用来指明出错位置

char property[30][20]={//属性表
	"$PROGRAM","$CONST","$VAR","$PROC",
	"$BEG",	"$END",	"$IF","$THEN",
	"$ELSE","$WHILE","$DO",	"$CALL","$READ","$WRITE",
	"$ID",	"$INT",	"$ASSIGN",	"$SEMICOLON",
	"$EQUAL","$PLUS","$SUBTRCT","$STAR",
	"$DIVIDE",	"$GREATER",	"$LESS",
	"$NONGREATER","$NONLESS","$UNEQUAL","$LPAR","$RPAR",
};

char _key[30][20]={//关键字及符号表
	"program","const","var","procedure","begin","end",
	"if","then","else","while","do","call","read","write",
	"标识符","整数",":=",";","=","+","-","*","/",">","<",
	">=","<=","<>","(",")",
};

void getCH(){//将下一个字符读入到ch中
	ch=getchar();
	if(ch=='\n') row++;
}

void getBC(){//如果ch中是空格换行,继续读入
	while(ch==' ' || ch=='\n' || ch=='\t'){
		getCH();
	}
}

void contact(){//将ch中的字符连接到strToken中
	int tmp=strlen(strToken);
	strToken[tmp]=ch;
	strToken[tmp+1]=0;
}

void clear(){//将strToken中的字符清零
	strToken[0]=0;
}

int letterkind(){//数字返回1,字母返回0,"><="返回-1,'\n''\r'返回-2,其他字符返回-3
	if(ch>='0' && ch<='9') return 1;
	else if((ch>='A' && ch<='Z') ||(ch>='a' && ch<='z')) return 0;
	else if(ch=='<' || ch=='>' || ch=='=') return -1;
	else if(ch=='\n' || ch=='\r')	return -2;
	else return -3;
}

int checKey(){//如果strToken中的字符全是字母送入此函数中查找对应的关键字id,找不到返回-1	
	for(int i=0;i<=13;i++){
		if(strcmp(strToken,_key[i])==0) return i;
	}
	return -1;
}

int checkToken(){//如果strToken中出现非数字和字母送入此函数中查找id,为了检测>=,<=,:=等字符,
				 //这里需要超前一位搜索
	getCH();
	if(letterkind()==-1){//letterkind()返回-1是比较符,-2是换行,-3是其他字符,
						 //如果下一位是"><="就连接上
		contact();
		getCH();
	}
	for(int i=16;i<=29;i++){
		if(strcmp(strToken,_key[i])==0) return i;
	}

	return -1;
}

int InsertInt(){//将字符串变成整数插入到数字表中,返回下标
	int num,i;
	num=0;
	for(i=0;i<(int)strlen(strToken);i++){
		num*=10;
		num+=(strToken[i]-'0');
	}
	intList[intListLen]=num;
	intListLen++;
	return intListLen-1;
}

void errorAction(){//处理出错的情况
	//标识符以非字母开头或者出现无法识别的字符
	char te=strToken[0];
	if(!(te>='A' && te<='Z') && !(te>='a' && te<='z')){
		while(letterkind()==1 || letterkind()==0){
			contact();
			getCH();
		}
		printf("error%d:(%d) \"%s\" is not legal.\n",error,row,strToken);//指出错误的行号和单词
	}
	clear();//将strToken中的字符清空继续处理后续的代码
	error++;
	
}

int main(){
	freopen("test.in","r",stdin);//文件输入,重定向
//	freopen("res.out","w",stdout);//结果输出到中间文件
	int count;//记录Word串的大小
	int tmp;

	count=0;	error=1;	row=1;
	getCH();
	getBC();
	
	while(ch!=EOF){//判断文件末尾
		if(letterkind()==0){//首字符是字母
			while(letterkind()==1 || letterkind()==0){
				contact();
				getCH();
			}
			tmp=checKey();
			if(tmp==-1){//标识符id
				Word[count].flag=0;
				Word[count].id=idListlen;
				strcpy(idList[idListlen],strToken);//标识符插入到idList表中
				idListlen++;	count++;
			}
			else{//关键字
				Word[count].flag=1;
				Word[count].id=tmp;		
				count++;
			}
		}
		else if(letterkind()==1){//首字符是数字
			while(letterkind()==1){
				contact();
				getCH();
			}
			if(letterkind()==0){//数字后跟字母,调用出错处理
				errorAction();
			}
			else{
				Word[count].flag=-1;//-1表示整数,存在数字表中
				Word[count].id=InsertInt();//整数插入数字表
				count++;
			}
		}
		else {//其他字符,调用checkToken()
			contact();
			tmp=checkToken();
			if(tmp==-1){//_key表中找不到对应项,调用出错处理
				errorAction();
			}
			else{
				Word[count].flag=1;//其他字符也在_key表中
				Word[count].id=tmp;
				count++;
			}
		}
		clear();//清空strToken
		getBC();
	}

	//打印结果
	printf("*****Analysis Result*****\n");
	printf("Token\tProperty\n");
	for(int i=0;i<count;i++){
		tmp=Word[i].id;
		if(Word[i].flag==1){//_key表
			printf("%s\t%s\n",_key[tmp],property[tmp]);
		}
		else if(Word[i].flag==0){//idList表
			printf("%s\t%s\n",idList[tmp],property[14]);
		}
		else {//intList表
			printf("%d\t%s\n",intList[tmp],property[15]);
		}
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -