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

📄 parse.c

📁 编译原理全套实验源代码。包括词法分析
💻 C
字号:
/* 
20031401008 褚超

实验一   词法分析程序

简易TC词法分析程序的实现

测试源文件:parse.c (即使用本程序的源文件即可)
可在程序输出文件output.TXT中查看程序运行结果

*/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include "symbol.h"

#define TRUE 1
#define FALSE 0


/* BUFLEN定义源文件行中的最大字符数 */
#define BUFLEN 256

#define TAB 8

/* 一个记号的最大的长度 */
#define MAXTOKENLEN 40

/* tokenString数组用来存储每个记号 */
char tokenString[MAXTOKENLEN+1];

/*	当前单词的类型	*/
int tokenType;

FILE *fin,*fout;

/* 词法分析程序初始化函数,完成各种符号表的构建 */
void init();

/* 扫描下一个字符:从输入缓冲区中获取字符,要注意维护当前字符所在的位置信息 
void scanChar()
{

}
*/

/*系统保留字判断函数
该函数用于判断当前输入单词是否是系统保留字*/
int iskeyword();

int isOperator();

int isSpecial(char ch);
/* 扫描下一个符号:根据当前字符ch来判断下一个符号可能是什么,调用相应的函数进行处理 */
void nextToken();
/*
1.当前如果是空白符,则进行过滤
2.当前是'_'或字母,则是标识符
3.当前是'.',若其后紧接着数字,则应该是一个小数,否则是一个普通符号DOT
4.当前是',',':'等单独的分界符。它们不是多个单词符号公有的字符,所以它们直接对应其所表示的单词符号
5.当前是/,情况较复杂
  1)后面紧跟一个/,单行注释
  2)后面是/*,多行注释
  3)后面紧跟'=',是除法赋值
  4)否则是一个简单的除法运算符
  (注意此种情况下如果是注释,则需要进行过滤)
6.当前是" ' "或者" " ",后面应该是字符常量和字符串常量,分别调用相应的函数进行处理
*/

/* 若是标识符,调用此函数对其余部分进行扫描 */
void scanIdent();

/* 若是数字,调用此函数继续扫描 */
void scanNum(int base);

/* 过滤源程序中的注释 */
void skipComment();

void scanOperator();


/*
 出错处理函数
*/
void error_manage(char error,int row,int col)
{                 
    printf("\nerror: %c ,row %d col %d",error,row,col);    /*报告出错符号和所在行数,列数*/
}





/* 当前处理的字符 */
char ch;

static char lineBuf[BUFLEN];	/* 保留当前行 */
static int linepos = 0;			/* 保存LineBuf中的当前位置 */
static int lineno = 0;
static int row=0,col=0;			/* 保存当前处理字符所在的行和列 */
static int bufsize = 0;			/* 当前缓存中保存的字符数 */
static int EOF_flag = FALSE;	/* 当遇到EOF(文件结束符)调整ungetNextChar的操作 */

/* 
getNextCharlineBuf取得下一个非空格的字符。如果读完了缓存中的全部字符,
就把新的一行读入缓存 
*/
static int getNextChar()
{ 
	if (!(linepos < bufsize))
	{ 
		lineno++;
		if (fgets(lineBuf,BUFLEN-1,fin))
		{ 
			bufsize = strlen(lineBuf);
			linepos = 0;
			return lineBuf[linepos++];
		}
		else
		{ 
			EOF_flag = TRUE;
			return EOF;
		}
	}
	else return lineBuf[linepos++];
}


/* ungetNextChar把一个字符退回到lineBuf缓存中 */
static void ungetNextChar(void)
{ 
	if (!EOF_flag) 
		linepos-- ;
}

FILE *fin,*fout;

void main()
{
	nextToken();
}

void nextToken()
{
	//FILE *fin,*fout;
	char filename[20];
	int count;
	printf("Please input the source file:");
	scanf("%s",filename);
	if((fin=fopen(filename,"r"))==NULL)
	{
		printf("\nCan't open the source file!\n");
		exit(1);
	}
	fout=fopen("output.txt","w");

	while( (ch=getNextChar())!= EOF )
	{
		switch(ch)
		{
		case ' ':
			col++;
			//ch=getNextChar();
			break;
		case '\t':
			col=(col/TAB*TAB)+TAB;
			//ch=getNextChar();
			break;
		case '\r':
			col=0;
			row++;
			//ch=getNextChar();
			break;
		case '\n':
			col=0;
			row++;
			//ch=getNextChar();
			break;				/* 过滤空白符号 */

		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
		case 'G':
		case 'H':
		case 'I':
		case 'J':
		case 'K':
		case 'L':
		case 'M':
		case 'N':
		case 'O':
		case 'P':
		case 'Q':
		case 'R':
		case 'S':
		case 'T':
		case 'U':
		case 'V':
		case 'W':
		case 'X':
		case 'Y':
		case 'Z':
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
		case 'g':
		case 'h':
		case 'i':
		case 'j':
		case 'k':
		case 'l':
		case 'm':
		case 'n':
		case 'o':
		case 'p':
		case 'q':
		case 'r':
		case 's':
		case 't':
		case 'u':
		case 'v':
		case 'w':
		case 'x':
		case 'y':
		case 'z':	
		case '_':
			scanIdent();
			
			break;

		case '0':
			ch=getNextChar();
			if(ch=='x' || ch=='X')
			{
				ch=getNextChar();
				if( !((ch>='0' && ch<='9') || ( ch>='a' && ch<='f') || (ch>='A' && ch<='F')) )
					error_manage(ch,lineno,col);
				tokenString[0]='0';
				tokenString[1]='x';
				scanNum(16);
			} else {
				/*回退前一个字符*/
				tokenString[0]='0';
				scanNum(8);
			}
			break;
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			scanNum(10);
			break;

		case '.':
			fprintf(fout,"DOT\t.\n");
			break;
		case ',':
			fprintf(fout,"COMMA\t,\n");
		     break;
		case ';':
			fprintf(fout,"SEMI\t;\n");
		    break;
		case '(':
			fprintf(fout,"LPAREN\t(\n");
		     break;
		case ')':
			fprintf(fout,"RPAREN\t)\n");
		     break;
		case '[':
			fprintf(fout,"LBRACE\t[\n");
		     break;
		case ']':
			fprintf(fout,"RBRACE\t]\n");
		     break;
		case '{':
			fprintf(fout,"LBRACKET\t{\n");
		    break;
		case '}':
			fprintf(fout,"RBRACKET\t}\n");
		    break;

		case '/':
			/* 消除注释部分 */
			ch=getNextChar();
			if (ch == '/') {
				do {
					ch=getNextChar();
				} while(ch != '\n');
			}
			else if (ch == '*') {
				count=0;
				ch=getNextChar();
				while(count!=2)
                {          /*当扫描到‘*’且紧接着下一个字符为‘/’才是注释的结束*/
					count=0;
					while(ch!='*')
						ch=getNextChar();
					count++;
					ch=getNextChar();
					if(ch=='/')
						count++;
					else
						ch=getNextChar();
				}
			}
			else if (ch == '=') {
				fprintf(fout,"SLASHEQ\t/=\n");
			}
			else
			{
				/*仅为一个单独的'/' */
				ungetNextChar();
				fprintf(fout,"SLASH\t/\n");	
			}
			break;
		case '\'':
			break;
		case '"':
			break;
		default:
			if (isSpecial(ch)) {
				scanOperator();
			}else if (ch==EOF) {
				fprintf(fout,"EOF");
			}
		}
	}
	fclose(fin);
	fclose(fout);
}



/*系统保留字判断函数
该函数用于判断当前输入单词是否是系统保留字*/
int iskeyword()
{
	int i;
	for(i=0;i<33;i++)
	{
		if(strcmp(tokenString,keywords[i])==0)
			return(keytype[i]);
	}
	if(i==ID)
		return(ID);
	else 
		return -1;
}

int isOperator()
{
	int i;
	for(i=0;i<32;i++)
	{
		if (strcmp(tokenString,operators[i])==0) {
			return(optype[i]-50);
		}
	}
	return -1;
}

/*是否是特殊字符*/
int isSpecial(char ch) {
    switch (ch) {
        case '!': case '%': case '&': case '*': case '?':
        case '+': case '-': case ':': case '<': case '=':
        case '>': case '^': case '|': case '~':
            return TRUE;
        default:
            return FALSE;
        }
}

void scanIdent()
{
	//char ch;
	int i=0,t;
		do {
			tokenString[i++]=ch;
			ch=getNextChar();	
	} while(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_')||((ch>='0')&&(ch<='9')));
	tokenString[i]='\0';
	if (ch!='\n') {
		ungetNextChar();
	}
	t=iskeyword(); /*判断是否是系统保留字*/
	if (t<33 && t>0) {
		/*输出关键字*/
		fprintf(fout,"KEYWORDS\t%s\n",tokenString);
	}
	/*	是标识符	*/
	if (t==ID) {
		fprintf(fout,"IDEN\t%s\n",tokenString);
	}
}



void scanNum(int base)
{
	int i=0;
	switch(base) {
	case 8:
		i=1;
		do {
			tokenString[i++]=ch;
			ch=getNextChar();
		} while(ch>='0'&&ch<='7');
		tokenString[i]='\0';
		if (ch!='\n') {
			ungetNextChar();
		}
		fprintf(fout,"OCT\t%s\n",tokenString);
		break;
	case 16:
		i=2;
		do {
			tokenString[i++]=ch;
			ch=getNextChar();
		} while((ch>='0' && ch<='9') || ( ch>='a' && ch<='f') || (ch>='A' && ch<='F'));
		tokenString[i]='\0';
		if (ch!='\n') {
			ungetNextChar();
		}
		fprintf(fout,"HEX\t%s\n",tokenString);
		break;
	default:
		do {
			tokenString[i++]=ch;
			ch=getNextChar();
		} while(ch>='0' && ch<='9');
		tokenString[i]='\0';
		if (ch!='\n') {
			ungetNextChar();
		}
		fprintf(fout,"INT\t%s\n",tokenString);
	}
}

void scanOperator()
{
	int i=0,t;
	do {
		tokenString[i++]=ch;
		ch=getNextChar();
	} while(isSpecial(ch));
	tokenString[i]='\0';
	if (ch!='\n') {
		ungetNextChar();
	}
    t=isOperator();
	if (t>=0 && t<32) {
		fprintf(fout,"OPERATOR\t%s\n",tokenString);
	}
	
}

⌨️ 快捷键说明

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