📄 plx.cpp
字号:
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 + -