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

📄 1.cpp

📁 PLX编译器,采用多遍式和自顶向下分析法. (内附测试代码)
💻 CPP
字号:
/*
PLX词法分析程序 
2007.11.4
*/
#include<stdio.h>
#include "2.h"
#define SYMBOLNUM 12//单个运算符个数
#define KEYNUM 18 //关键字个数
#define MAXNOBIT 50 //数字的最大位数
/**************************************************************************************/
//关键字表
char keywords[KEYNUM][KEYNUM]={
	"and",
	"begin",
	"do",
	"else",
	"end",
	"false",
	"if",
	"integer",
	"logical",
	"not",
	"or",
	"program",
	"repeat",
	"then",
	"true",
	"until",
	"while",
	"write",
};
//符号表(单个)
char symbol1[SYMBOLNUM]={'*' , '/' , '(' , ')' ,
						 '+' , '-' , '=' , ',' ,             
			             '<' , '>' , '.' , ';' ,
						 
};
//符号表(组合)
char symbol2[10][3]={ "<=" , ">="  , "/=" ,":=" };
//输出格式
struct out
{
	int  type1;//关键字1 数字2 标识符3 运算符4
	int  type2;//小类 只能用int 可能会超过9
	char name[12];//数字以外的(字符串形式)
	int  value;//数字的值
	int lineno;//行号
    //int	column;
};

/**************************************************************************************/
void fengxi(char *buf,//保存读入的一行
			char* symbol,//符号表
			int num,//该行的字符数
			int lineno,//行号
			FILE *fp//输出文件
			);

int isakey(char *token);
int isasymbol2(char *token);
void output(int type1,int type2,char *name,int value,int lineno,FILE *fp);
int chartonum(char *number,int len);
/**************************************************************************************/
int main()
{
	   FILE *fp1;//源程序
	   FILE *fp2;//生成程序
	   int lineno=0;
	   int num=0;

	   if((fp1=fopen("源代码.txt","r"))==NULL)
	   {
 			printf("不能打开源文件\n");
			return 0;
	   }//if

	   if((fp2=fopen("词法分析结果.txt","w"))==NULL)
	   {
 			printf("不能打开文件\n");

			return 0;
	   }//if

	   while(num!=-1)
	   {
			char buf[50];//保存读入的一行
			num=getline(buf,fp1,'\n');
			if(num>0)
			{
				//printf("L%d ",lineno);//打印行号
				putline(buf,num);
				lineno++;
				fengxi(buf,symbol1,num,lineno,fp2);
				printf("\n");
			}//if
		}//while
	    fclose(fp1);
		fclose(fp2);

  return 0;
}//main

void fengxi(char *buf,char* symbol,int num,int lineno,FILE *fp)
{
	char c=' ';//保存取道的字符
	char NULLL[32]="         ";//表示数字的name属性
	int value=0;//数字的值
	int tn=0;//数字的位数(字符串形式)
	char token[32];//保存token
	int ti=0;//token count
	char number[MAXNOBIT];//数字的最大位数
	int state=-1;// 0 标识符 1 常数 2运算符 -1非法字符  4字符
	int type2;//保存关键字,运算符的编号

	for(int i=0;i<num;)
	{	
		ti=0;
		value=0;
		int j;//临时变量
		char m[2]=" ";//保存单个运算符
		state=-1;
		c=buf[i];
		tn=0;
		type2=-1;

//token初始化
		for(j=0;j<32;j++)
			token[j]=' ';
//number初始化
		for(j=0;j<50;j++)
			number[j]=' ';
//挑砖部分
		if(c=='\'')							state=4;
		else if(isaletter(c)||c=='_')		state=0;
		else if(isanumber(c))				state=1;
		else if(c==' '||c==9){i++;continue;}//9是TAB
		else								state=2;
		//else if(isasymbol(c,symbol))		state=2;
//跳转后的处理部分
		switch(state)
		{
		case 0://标识符
                while(isaletter(c)||isanumber(c)||c=='_')
				{ 
					if(i==num)break;
					token[ti++]=c;
					c=buf[++i];        
				}//while

                token[ti]='\0';
			   
				if(isakey(token)!=-1)
				{
					type2=isakey(token);
					output(1,type2,token,0,lineno,fp);//关键字
				}//if
				else 
				{	
					output(3,1,token,0,lineno,fp);//标识符
				}//else
				break;//case 0

		case 1://常数
			{
				tn=0;
				while(isanumber(c))
				{    
						if(i==num)break;
						number[tn++]=c;	
					    c=buf[++i];        
				}
				
                number[tn]='\0';
                value=chartonum(number,tn);
				output(2,1,NULLL,value,lineno,fp);
				break;//case 1
			}

		case 2://运算符
				//二元运算符
				{
					char local[3];
					local[0]=c;
					local[1]=buf[i+1];
					if(isasymbol2(local)!=-1)
					{
						type2=isasymbol2(local);
						local[2]='\0';
						output(4,type2,local,0,lineno,fp);
						i=i+2;
						break;
					}
				}
				
				i++;
				m[0]=c;
				m[1]='\0';

				if(isasymbol(c,symbol)!=-1)
				{

					output(5,isasymbol(c,symbol),m,0,lineno,fp);
				}
                else 
				{
					output(6,1,m,value,lineno,fp);//非法字符
				}		
				break;
		case -1://非法字符 
				i++;			
                output(5,1,NULLL,value,lineno,fp);
				break;

		}//switch
	}//for
}
/**************************************************************************************/
int isakey(char *token)
{
	for(int i=0;i<KEYNUM;i++)
		if(strncmp(keywords[i],token,strlen(keywords[i]))==0)return i;

	return -1;
}

int isasymbol2(char *token)
{	for(int i=0;i<4;i++)
		if(strncmp(symbol2[i],token,strlen(symbol2[i]))==0)return i;
	return -1;
}

void output(int type1,int type2,char *name,int value,int lineno,FILE *fp)
{
	    out output1;
		output1.type1=type1;
		output1.type2=type2;

		//strcmp(output1.name,name);
		for(int i=0;i<strlen(name);i++)
             output1.name[i]=name[i];
		for(;i<11;i++)
             output1.name[i]=' ';
		output1.name[11]='\0';

		output1.value=value;
		output1.lineno=lineno;
        fwrite(&output1,sizeof(output1),1,fp);
		fprintf(fp,"\n");

		printf("%d %d %s %d %d",output1.type1,output1.type2,output1.name,output1.value,output1.lineno);
        printf("\n");
		
                   // printf(" 关键字 行%d\n",lineno);
				//	fprintf(fp," 关键字 行%d\n",lineno);
}

int chartonum(char *number,int len)
{
	int value=number[0]-'0';
	for(int i=1;i<len;i++)
		value=value*10+(number[i]-'0');
	return value;
}
/*
思路

关键字P187
数字 
标识符 (变量,过程名)
其他符号 (组合 单个)

输出格式
大类  小类  名称      值
int    int  char[12]  int
*/

/*
2008.11.4
改进 输出的统一格式 写成函数 不再是分散到各处

*/

⌨️ 快捷键说明

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