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

📄 scanner.cpp

📁 c语言编写的词法分析器 可以用于PASCAL语言
💻 CPP
字号:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>          //定义屏幕操作函数


enum M{INT10,INT8,INT16,REAL10,REAL8,REAL16,IDN,ASG,ADD,SUB,MUL,DIV,EQ,GT,LT,LP,RP,SEMI,ERR,WHILE,IF,ELSE,DO,THEN};
    //定义十进制、八进制、十六进制的整型和浮点型等数值的种别;以及变量、赋值符号、加减乘除、等于、大于、小于、左括号、右括号、分号以及出错

//函数声明
int scan();                     //词扫描函数
void printToken(int kind);      //最后的输出函数

int isdigit(char ch);		//判断是否是数字
int isalpha(char ch);		//判断是否是字母
int isKeyword(char *a);		//判断是否是关键字
int isRight(char ch);		//检查输入是否合法
void SaveSymbolList(char *a);		//将标识符存入符号表symbolList
int isDEC(char *a);		//判断是否为十进制整数
int isOCT(char *a);		//判断是否为八进制整数
int isHEX(char *a);		//判断是否为十六进制整数
int isRealDEC(char *a);		//判断是否为十进制浮点数
int isRealOCT(char *a);		//判断是否为八进制浮点数
int isRealHEX(char *a);		//判断是否为十六进制浮点数
void clearToken();   //清空Token[]
void Reverse10(char *a);	//将其他进制转换成整型,并转为十进制数,存入整数表intList
void ReverseReal10(char *a);	//将其他进制转换成转为十进制数,存入浮点表floatList

//宏定义
char token[20];
char empty[20];
char symbolList[20][20];		//符号表
int intList[50]={0};		//存储整数,初值均为0
int i=-1;       //控制token[]的数组下标变量
int input[100];   //存放输入的各种符号的单词种别

float floatList[50]={0};		//存储浮点数,初值均为0

int s=-1,n=-1;      //n为整数表的下标量
int m=-1;          // m为浮点数表的下标量
int en;				//控制词法分析循环的使能变量
int iorf=0;          //标定是浮点型还是整型
int t=0;

main() {
	char yn=' ';
	int kind;
	int num;
	while(1) {
		en=1;
		printf("\n");
		printf("******************<Scanner for a tiny programming language>****************\n");
                printf("please enter:\n");
		while(en){
			clearToken();
			kind = scan();		//扫描词
			input[t]=kind;
			t++;
			printToken(kind);
		}

			i=-1; 		//将i再次初始化
			for(num=0;num<t;num++)
		    	input[num]=0;
			t=0;
		printf("\n\n");
	} 
	return 0;
}

int scan() {
	char ch;
	int key;
	while(1) {
		ch=getchar();		     //读取一个字符
		while(ch==' ') 		     //若为空格,则跳过
			ch=getchar();        //继续读取下一个
		
		
		if(isRight(ch)==0&&ch!='\n') {
			return ERR;	//如果输入字符不合法,出错
		}
		else if(isdigit(ch)) {		//如果第一个字符是数字
			i++; 
			token[i]=ch;		//将读入的字符存入暂存表	 
			ch=getchar();     
			i++;
			while(isdigit(ch)||ch=='x'||ch=='X'||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F')||ch=='.') {	//继续读入后续的整数字符
        		token[i]=ch;    //继续存入token
				ch=getchar();
				i++;
			}         
			token[i]='\0';		//该词的结束
			ungetc(ch,stdin);	//把一个字符退回到输入流中
			if(isDEC(token)) {		//为十进制的数的输入格式
				iorf=0;
				n++;
				Reverse10(token);   //转化为真正的十进制数
				if(ch=='\n') en=0;   
				return INT10;
			}
			else if(isOCT(token)) {		//为八进制数的输入格式
				iorf=0;
				n++;
				Reverse10(token);       //转化为十进制数
				if(ch=='\n') en=0;
				return INT8;
			}
			else if(isHEX(token)){		//为十六进制的输入格式
				n++;
				iorf=0;
				Reverse10(token);        //转化为十进制数
				if(ch=='\n') en=0;
				return INT16;
			}
			else if(isRealDEC(token)) {		//为十进制的浮点数的输入格式
				iorf=1;
				m++;
				ReverseReal10(token);   //转化为真正的十进制数
				if(ch=='\n') en=0;   
				return REAL10;
			}
			else if(isRealOCT(token)) {		//为八进制浮点数的输入格式
				m++;
				iorf=1;
				ReverseReal10(token);       //转化为十进制数
				if(ch=='\n') en=0;
				return REAL8;
			}
			else if(isRealHEX(token)){		//为十六进制的浮点数输入格式
				m++;
				iorf=1;
				ReverseReal10(token);        //转化为十进制数
				if(ch=='\n') en=0;
				return REAL16;
			}

			else {			//出错
				if(ch=='\n') en=0;
				return ERR;
			}
		}
		
		else if(isalpha(ch)) {		//如果第一个字符是字母
			i++;
			s++;
			token[i]=ch; 
			ch=getchar();
			i++;
			while(isalpha(ch) || isdigit(ch)) {
				token[i]=ch; 
				ch=getchar();
                i++;
			}
			token[i]='\0';
			ungetc(ch,stdin);
			key = isKeyword(token);		//看是否为关键字
			if(key==WHILE)  {
				if(ch=='\n') en=0;
				return WHILE;	//是关键字,则返回WHILE
			}
			if(key==DO)  {
				if(ch=='\n') en=0;
				return DO;	//是关键字,则返回DO
			}
			if(key==ELSE)  {
				if(ch=='\n') en=0;
				return ELSE;	//是关键字,则返回ELSE
			}
			if(key==IF)  {
				if(ch=='\n') en=0;
				return IF;	//是关键字,则返回IF
			}
			if(key==THEN)  {
				if(ch=='\n') en=0;
				return THEN;	//是关键字,则返回THEN
			}
			else {
				SaveSymbolList(token);	//将token存入符号表
				if(ch=='\n') en=0;
			 	return IDN;		//返回标识符
			}
		}

		else if(ch==':') {		//如果第一个字符是冒号
			i++;
			token[i]=ch;
			ch=getchar();
			i++;
			if(ch=='=') {
				token[i]=ch; 
				i++;
				token[i]='\0';  
				if(ch=='\n') en=0;
				return ASG;		//返回付值号
			}
			else {
				if(ch=='\n') en=0;
				return ERR;	//出错
			}
		}
		else if(ch=='+') {		//加号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return ADD; 
		}
		else if(ch=='-') {		//减号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return SUB;
		}	
		else if(ch=='*') {		//星号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return MUL;
		}	
		else if(ch=='/') {		//除号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return DIV;
		}	
		else if(ch=='=') {		//等于号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return EQ;
		}	
		else if(ch=='>') {		//大于号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return GT;
		}	
		else if(ch=='<') {		//小于号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return LT;
		}	
		else if(ch=='(') {		//左括号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return LP;
		}	
		else if(ch==')') {		//右括号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return RP; 

		}	
		else if(ch==';') {		//分号
			i++;
			token[i]=ch; 
			i++;
			token[i]='\0';
			if(ch=='\n') en=0;
			return SEMI; 
		}	
	}
}

void printToken(int kind) {	//打印
	printf("\n");
	switch(kind) {
		case INT10:printf("%s:  < INT10, %d >",token,intList[n]);
			break;
		case INT8: printf("%s:  < INT8, %d >",token,intList[n]);
			break;
		case INT16:printf("%s:  < INT16, %d >",token,intList[n]);
			 break;
		case REAL10:printf("%s:  < REAL10, %f >",token,floatList[m]);
			break;
		case REAL8: printf("%s:  < REAL8, %f >",token,floatList[m]);
			break;
		case REAL16:printf("%s:  < REAL16, %f >",token,floatList[m]);
			 break;
		case WHILE: printf("%s:  < WHILE, - > ",token);
			break; 
		case DO: printf("%s:  < DO, - > ",token);
			break; 
		case IF: printf("%s:  < IF, - > ",token);
			break; 
		case ELSE: printf("%s:  < ELSE, - > ",token);
			break; 
		case THEN: printf("%s:  < THEN, - > ",token);
			break; 
		case IDN: printf("%s:  < IDN,  %s >",symbolList[s],symbolList[s]);
			break;
		case ASG: printf("%s:  < %s, - >",token,token);
			break;
		case ADD: printf("%s:  < %s, - >",token,token);
			break;
		case SUB: printf("%s:  < %s, - >",token,token);
			break;
		case MUL: printf("%s:  < %s, - >",token,token);
			break;
		case DIV: printf("%s:  < %s, - >",token,token);
			break;
		case EQ: printf("%s:  < %s, - >",token,token);
			break;
		case GT: printf("%s:  < %s, - >",token,token);
			break;
		case LT:printf("%s:  < %s, - >",token,token);
			break;
		case LP: printf("%s:  < %s, - >",token,token);
			break;
		case RP: printf("%s:  < %s, - >",token,token);
			break;
		case SEMI: printf("%s:  < %s, - >",token,token);
			break;
		case ERR: printf("ERROR!");
			break;
		default: break;
	}
	printf("\n");
	
}

int isRight(char ch) {		//判断是否出错
	if(((ch>='0')&&(ch<='9'))||((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||(ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch=='=')||(ch=='<')||(ch=='>')||(ch=='(')||(ch==')')||(ch==':')||(ch==';'))
		return 1;
	else return 0;
}

int isdigit(char ch) {		//判断是否为数字
	if((ch>='0')&&(ch<='9'))
		return 1;
	else return 0;
}

int isDEC(char *a) {		//判断是否为十进制整数
	int x=0;
	do {
		if((a[0]=='0'&&a[1]=='\0')||(a[0]>'0'&&isdigit(a[x]))) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0') return 1;
	else return 0;
}

int isOCT(char *a) {		//判断是否为八进制整数
	int x=0;
	do {
		if(a[0]=='0'&&(a[x]>='0'&&a[x]<='7')) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0'&&a[0]=='0') return 1;
	else return 0;
}

int isHEX(char *a) {		//判断是否为十六进制整数
	int x=2;
	do {
		if((a[0]=='0')&&(a[1]=='x'||a[1]=='X')&&(isdigit(a[x])||(a[x]>='a'&&a[x]<='f')||(a[x]>='A'&&a[x]<='F'))) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0'&&a[0]=='0'&&(a[1]=='x'||a[1]=='X')&&a[2]!='\0') return 1;
	else return 0;
}


int isRealDEC(char *a) {		//判断是否为十进制浮点数
	int x=0;
	do {
		if((a[0]=='0'&&a[1]=='\0')||(a[0]=='0'&&a[1]=='.')||(a[0]>'0'&&(isdigit(a[x])||a[x]=='.'))) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0') return 1;
	else return 0;
}

int isRealOCT(char *a) {		//判断是否为八进制浮点数
	int x=0;
	do {
		if(a[0]=='0'&&a[1]!='.'&&((a[x]>='0'&&a[x]<='7')||a[x]=='.')) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0'&&a[0]=='0') return 1;
	else return 0;
}

int isRealHEX(char *a) {		//判断是否为十六进制浮点数
	int x=2;
	do {
		if((a[0]=='0')&&(a[1]=='x'||a[1]=='X')&&(isdigit(a[x])||(a[x]>='a'&&a[x]<='f')||(a[x]>='A'&&a[x]<='F')||a[x]=='.')) {
			x++;
			continue;
		}
		else break;
	} while(a[x]!='\0');
	if(a[x]=='\0'&&a[0]=='0'&&(a[1]=='x'||a[1]=='X')&&a[2]!='\0') return 1;
	else return 0;
}


void Reverse10(char *a) {	//将其他进制转换成整型,并转为十进制数,存入整数表intList[n]
	int x=0;
	int temp[80];
	if(a[0]=='0'&&(a[1]=='x'||a[1]=='X')) {		//如果为十六进制
		while(a[x]!='\0') {
			if(a[x]>='a'&&a[x]<='f') {		//小写a-f,转为相应整型
				temp[x]=a[x]-87;
				x++;
			}
			else if(a[x]>='A'&&a[x]<='F') {		//大写A-F,转为相应整型
				temp[x]=a[x]-55;
				x++;
			}
			else {
				temp[x]=a[x]-48;		//'0'-'9',转为整型
				x++;
			}
		}
		temp[x]=11111;
		x=2;
		while(temp[x]!=11111) {
			intList[n]=intList[n]*16+temp[x];	//转为十进制
			x++;
		}		
	}
	else if(a[0]=='0') {				//如果为八进制
		while(a[x]!='\0') {
			temp[x]=a[x]-'0';		//转为整型
			x++;
		}
		temp[x]=11111;
		x=1;
		while(temp[x]!=11111) {
			intList[n]=intList[n]*8+temp[x];	//转为十进制
			x++;
		}		
	}
	
	else {							//为十进制
		while(a[x]!='\0') {
			temp[x]=a[x]-'0';		//转为整型
			x++;
		}
		temp[x]=11111;
		x=0;
		while(temp[x]!=11111) {
			intList[n]=intList[n]*10+temp[x];
			x++;
		}	
	}
}


void ReverseReal10(char *a) {	//将其他进制整型转换成整型,并转为十进制数,存入整数表intList[n]
	int x=0;
	int point=0;      //指明第几个字符是小数点
	float p=0.1;      //小数部分各位的级数
	float pp=0.08;
	float ppp=0.0625;
	int temp[80];
	if(a[0]=='0'&&(a[1]=='x'||a[1]=='X')) {		//如果为十六进制
		while(a[x]!='\0') {

          	if(a[x]=='.'){
				point=x;
				temp[x]=100;      //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
				x++;
			}
			else if(a[x]>='a'&&a[x]<='f') {		//小写a-f,转为相应整型
				temp[x]=a[x]-87;
				x++;
			}
			else if(a[x]>='A'&&a[x]<='F') {		//大写A-F,转为相应整型
				temp[x]=a[x]-55;
				x++;
			}
			else {
				temp[x]=a[x]-48;		//'0'-'9',转为整型
				x++;
			}
		}
		temp[x]=11111;
		x=2;
		while(temp[x]!=11111&&temp[x]!=100) {        //整数部分的处理
			floatList[m]=floatList[m]*16+temp[x];
			x++;
		}	
		if(temp[x]==100)
		    x++;
		while(temp[x]!=11111){
		    floatList[m]=floatList[m]+temp[x]*ppp;
			ppp=ppp/16;
			x++;
		}	
	}
	else if(a[0]=='0'&&a[1]!='.') {				//如果为八进制
		while(a[x]!='\0') {
				if(a[x]=='.'){
				point=x;
				temp[x]=10;      //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
			}
			else
		    	temp[x]=a[x]-'0';		//转为整型
			x++;
		}
		temp[x]=11111;
		x=1;
		while(temp[x]!=11111&&temp[x]!=10) {        //整数部分的处理
			floatList[m]=floatList[m]*8+temp[x];
			x++;
		}	
		if(temp[x]==10)
		    x++;
		while(temp[x]!=11111){
		    floatList[m]=floatList[m]+temp[x]*pp;
			pp=pp*0.08;
			x++;
		}	
	}
	
	else {							//为十进制
		while(a[x]!='\0') {
			if(a[x]=='.'){
				point=x;
				temp[x]=10;      //因为十进制数的各个位上不可能出现10,所以用10来表示小数点所在的位置
			}
			else
			    temp[x]=a[x]-'0';		//转为整型
			x++;
		}
		temp[x]=11111;
		x=0;
		while(temp[x]!=11111&&temp[x]!=10) {        //整数部分的处理
			floatList[m]=floatList[m]*10+temp[x];
			x++;
		}	
		if(temp[x]==10)
		    x++;
		while(temp[x]!=11111){
		    floatList[m]=floatList[m]+temp[x]*p;
			p=p*0.1;
			x++;
		}
	}
}

int isalpha(char ch) {		//判断是否为字符
	if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||ch=='_'||ch=='.')
		return 1;
	else return 0;
}

int isKeyword(char *a) {	//关键字 if  then  else  while  do
	if ((a[0]=='i')&&(a[1]=='f')&&(a[2]=='\0'))
		return IF;
	if ((a[0]=='t')&&(a[1]=='h')&&(a[2]=='e')&&(a[3]=='n')&&(a[4]=='\0'))
		return THEN;
	if ((a[0]=='e')&&(a[1]=='l')&&(a[2]=='s')&&(a[3]=='e')&&(a[4]=='\0'))
		return ELSE;
	if ((a[0]=='w')&&(a[1]=='h')&&(a[2]=='i')&&(a[3]=='l')&&(a[4]=='e')&&(a[5]=='\0'))
		return WHILE;
	if ((a[0]=='d')&&(a[1]=='o')&&(a[2]=='\0'))
		return DO;
	return 0;
}

void SaveSymbolList(char *a) {	//存入符号表symbolList
	int x=0;
	do {
		symbolList[s][x]=a[x];
		x++;
	}while(a[x-1]!='\0');
}

void clearToken(){
	int t;
	i=-1;
	for(t=0;t<=19;t++)
		token[t]=empty[t];
}

⌨️ 快捷键说明

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