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

📄 plx.cpp

📁 PLx语言的编译器。PLx语言是一种类Pascal语言
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		if(disp < 0)
			ErrMsg("标识符未定义");
		else if(VarTab[disp].logic)
		{
			GetToken();
			NewInst(OP_LOD, disp);
		}
		else
			AnalyzeRE();
	}
	else if(Token.type == TT_NUMBER)
		AnalyzeRE();
	else if(IsKeyword(KW_TRUE) || IsKeyword(KW_FALSE))
	{
		NewInst(OP_LIT, IsKeyword(KW_TRUE) ? 1 : 0);
		GetToken();
	}
	else if(IsKeyword(KW_NOT))
	{
		GetToken();
		AnalyzeBF();
		NewInst(OP_OPR, 5);
	}
	else if(IsSymbol('('))
	{
		GetToken();
		AnalyzeBE();
		if(IsSymbol(')'))
			GetToken();
		else
		{
			ErrMsg("缺少“)”");
			while(!(IsSymbol(')') || IsSymbol(';') || Token.type == TT_KEYWORD))
				GetToken();
		}
	}
	else
	{
		ErrMsg("非法表达式项");
		while(!(IsSymbol(')') || IsSymbol(';') || Token.type == TT_KEYWORD))
			GetToken();
	}
}

void AnalyzeBT()
{
	AnalyzeBF();
	while(IsKeyword(KW_AND))
	{
		GetToken();
		AnalyzeBF();
		NewInst(OP_OPR, 6);
	}
}

void AnalyzeBE()
{
	AnalyzeBT();
	while(IsKeyword(KW_OR))
	{
		GetToken();
		AnalyzeBT();
		NewInst(OP_OPR, 7);
	}
}

void AnalyzeSS(KEYWORD follow)
{
	for(;;)
	{
		if(IsKeyword(follow) || IsKeyword(KW_END))
			break;
		if(Token.type == TT_IDENT)
		{
			int disp = FindVar(Token.ident);
			if(disp < 0)
				ErrMsg("标识符未定义");
			GetToken();
			if(IsSymbol(':='))
			{
				GetToken();
				if(VarTab[disp].logic)
					AnalyzeBE();
				else
					AnalyzeAE();
				NewInst(OP_STO, disp);
			}
			else
			{
				ErrMsg("缺少“:=”");
				while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
					GetToken();
			}
		}
		else if(IsKeyword(KW_IF))
		{
			int p0, p1;
			GetToken();
			AnalyzeBE();
			if(IsKeyword(KW_THEN))
				GetToken();
			else
				ErrMsg("缺少“THEN”");
			p0 = CurProgCount();
			NewInst(OP_JPC, 0);
			AnalyzeSS(KW_ELSE);
			if(IsKeyword(KW_ELSE))
			{
				GetToken();
				p1 = CurProgCount();
				NewInst(OP_JMP, 0);
				BackPatch(p0, CurProgCount());
				AnalyzeSS(KW_END);
				BackPatch(p1, CurProgCount());
			}
			else
				BackPatch(p0, CurProgCount());
			if(IsKeyword(KW_END))
				GetToken();
			else
			{
				ErrMsg("缺少“END”");
				while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
					GetToken();
			}
		}
		else if(IsKeyword(KW_WHILE))
		{
			int p0, p1;
			GetToken();
			p0 = CurProgCount();
			AnalyzeBE();
			if(IsKeyword(KW_DO))
				GetToken();
			else
				ErrMsg("缺少“DO”");
			p1 = CurProgCount();
			NewInst(OP_JPC, 0);
			AnalyzeSS(KW_END);
			NewInst(OP_JMP, p0);
			BackPatch(p1, CurProgCount());
			if(IsKeyword(KW_END))
				GetToken();
			else
			{
				ErrMsg("缺少“END”");
				while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
					GetToken();
			}
		}
		else if(IsKeyword(KW_REPEAT))
		{
			int p = CurProgCount();
			GetToken();
			AnalyzeSS(KW_UNTIL);
			if(IsKeyword(KW_UNTIL))
			{
				GetToken();
				AnalyzeBE();
				NewInst(OP_JPC, p);
			}
			else
			{
				ErrMsg("缺少“UNTIL”");
				while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
					GetToken();
			}
		}
		else if(IsKeyword(KW_WRITE))
		{
			GetToken();
			AnalyzeAE();
			NewInst(OP_OPR, 14);
		}
		else
		{
			ErrMsg("非法语句");
			while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
				GetToken();
		}

		if(IsSymbol(';'))
			GetToken();
		else if(!(IsKeyword(follow) || IsKeyword(KW_END)))
		{
			ErrMsg("缺少“;”");
			while(!(IsSymbol(';') || IsKeyword(follow) || IsKeyword(KW_END)))
				GetToken();
			if(IsSymbol(';'))
				GetToken();
		}
	}
}

void AnalyzePROG()
{
	if(IsKeyword(KW_PROGRAM))
		GetToken();
	else
	{
		ErrMsg("缺少“PROGRAM”");
		while(!(IsKeyword(KW_INTEGER) || IsKeyword(KW_LOGICAL) || IsKeyword(KW_BEGIN)))
			GetToken();
	}
	AnalyzeDS();
	NewInst(OP_INT, VarTab.size());
	if(IsKeyword(KW_BEGIN))
		GetToken();
	else
		ErrMsg("缺少“BEGIN”");
	AnalyzeSS(KW_END);
	NewInst(OP_HLT, 0);
	if(IsKeyword(KW_END))
		GetToken();
	else
	{
		ErrMsg("缺少“END”");
		while(!IsSymbol('.'))
			GetToken();
	}
	if(!IsSymbol('.'))
		ErrMsg("缺少“.”");
}

/******************************************************************************\
*                                    虚拟机                                    *
\******************************************************************************/

void ResetVM()
{
	ProgCount = 0;
	DataStack.clear();
}

void DisplayVM()	//	显示虚拟机界面
{
	system("CLS");	//	清屏
	int n = InstTab.size(), t = DataStack.size() - 1;
	int v = VarTab.size(), i;
	printf("Prog:\tAddr\tInstruction\t Data:\tAddr   Value  (  type\tname )\n"
		"-----\t----\t-----------\t -----\t----   -----  ----------------\n");
	for(i = 0; i < n || i <= t; i++)
	{
		if(i < n)
		{
			if(i == ProgCount)
				printf("p -->\t");		//	显示程序指针
			else
				printf("\t");
			PrintInst(i);		//	显示指令
		}
		else
			printf("\t\t\t");
		if(i <= t)
		{
			if(i == t)
				printf("\t t -->\t");	//	数据栈顶指针
			else
				printf("\t\t");
			printf("%04d%8d", i, DataStack[i]);	//	数据栈内容
			if(i < v)
				printf("  ( %s %s )", VarTab[i].logic ? "logical" : "integer", VarTab[i].name);
		}
		printf("\n");
	}
}

bool StepVM()	//	虚拟机单步运行,指令系统见设计文档
{
	OPCODE op = InstTab[ProgCount].op;
	int n = InstTab[ProgCount].n;
	int t = DataStack.size() - 1;
	ProgCount++;

	switch(op)
	{
	case OP_INT:
		while(n > 0)
		{
			DataStack.push_back(0);
			n--;
		}
		break;
	case OP_HLT:
		return true;
	case OP_LIT:
		DataStack.push_back(n);
		break;
	case OP_LOD:
		DataStack.push_back(DataStack[n]);
		break;
	case OP_STO:
		DataStack[n] = DataStack[t];
		DataStack.pop_back();
		break;
	case OP_JMP:
		ProgCount = n;
		break;
	case OP_JPC:
		if(DataStack[t] == 0)
			ProgCount = n;
		DataStack.pop_back();
		break;
	case OP_OPR:
		switch(n)
		{
		case 0:
			DataStack[t] = -DataStack[t];
			break;
		case 1:
			DataStack[t - 1] += DataStack[t];
			DataStack.pop_back();
			break;
		case 2:
			DataStack[t - 1] -= DataStack[t];
			DataStack.pop_back();
			break;
		case 3:
			DataStack[t - 1] *= DataStack[t];
			DataStack.pop_back();
			break;
		case 4:
			DataStack[t - 1] /= DataStack[t];
			DataStack.pop_back();
			break;
		case 5:
			DataStack[t] = !DataStack[t];
			break;
		case 6:
			DataStack[t - 1] = DataStack[t - 1] && DataStack[t];
			DataStack.pop_back();
			break;
		case 7:
			DataStack[t - 1] = DataStack[t - 1] || DataStack[t];
			DataStack.pop_back();
			break;
		case 8:
			DataStack[t - 1] = DataStack[t - 1] == DataStack[t];
			DataStack.pop_back();
			break;
		case 9:
			DataStack[t - 1] = DataStack[t - 1] != DataStack[t];
			DataStack.pop_back();
			break;
		case 10:
			DataStack[t - 1] = DataStack[t - 1] < DataStack[t];
			DataStack.pop_back();
			break;
		case 11:
			DataStack[t - 1] = DataStack[t - 1] <= DataStack[t];
			DataStack.pop_back();
			break;
		case 12:
			DataStack[t - 1] = DataStack[t - 1] > DataStack[t];
			DataStack.pop_back();
			break;
		case 13:
			DataStack[t - 1] = DataStack[t - 1] >= DataStack[t];
			DataStack.pop_back();
			break;
		case 14:
			printf("%d\n", DataStack[t]);
			DataStack.pop_back();
			Pause=true;
			break;
		}
		break;
	}
	return false;
}

/******************************************************************************\
*                                    主函数                                    *
\******************************************************************************/

void main()
{
	char buf[256];
	printf("请输入要编译的源文件名(默认为“test.plx”):");
	gets(buf);
	if(buf[0] == '\0')
		strcpy(buf,"test.plx");
	ErrNum = 0;
	if(!OpenSourceFile(buf))
	{
		printf("源文件“%s”无法打开。\n",buf);
		return;
	}
	VarTab.clear();
	InstTab.clear();
	try {
		AnalyzePROG();
	} catch(...) { }
	fclose(SourceFile);
	if(ErrNum == 0)
	{
		ResetVM();
		for(;;)
		{
			DisplayVM();
			printf("\n虚拟机命令[ ESC=退出,G=运行,其它键=单步 ]>");
			char ch = tolower(getch());
			printf("\n");
			if(ch == 27) return;
			if(ch == 'g')
			{
				while(!StepVM());
				if(Pause)
				{
					printf("任意键继续。。。");getch();
				}
				break;
			}
			if(StepVM()) break;
			if(Pause)
			{
				Pause = false;
				printf("任意键继续。。。");getch();
			}
		}
		DisplayVM();
		printf("\n程序正常中止。\n");
	}
}

⌨️ 快捷键说明

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