编译原理之解释执行

源码:https://github.com/yanguojun123/Compile

生成目标代码后就可进行解释执行了。

整体思路:

1.具体实现:

     扫描目标代码表,根据每条代码在的作用进行相应的实现。在这个实验中,我用了一个int数组来记录活动,用了一个栈来进行计算。有着指向代码的指针sp,当sp的值指向最后一条代码时则结束。

每条代码的具体实现:

1.1 jmp:

直接将代码指针更改为a域里的值,如果此时代码指针为0,则把主过程的动态链,返回地址和静态链填到活动记录数组里。

1.2 opr

根据a域里的值进行相应的计算,例如如果为1,则将栈顶和次栈顶的数相加,然后将其结果保存到栈顶。如果为0,表示退出此过程,则将其活动记录数组的指针指向前一个过程的动态链,然后修改当前的返回地址和静态链。

1.3 lit

将其a域的值放到栈顶。

1.4 lod

   先根据层差找到其变量所在的动态链,如果层差为0,则为当前过程的动态链,如果不为0,则先取出静态链的中地址,找到上一层的动态链,并在循环中多次进行层差次数次,再根据a域的相对地址将对应的值放到栈顶。

1.5 sto

   跟lod类似,不过是修改这个变量的值为栈顶的值。

1.6 cal

   根据过程的层差填写要调用过程的动态链,返回地址和静态链。动态链的内容即为当前活动记录指针的值,而返回地址为当前代码指针的下一位,如果层差为0,则将上一个动态链的内容填到新的静态链中,否则将上一个静态链中的内容填入。

1.7 jpc

   如果栈顶的值为0即表示非真就将代码指针修改为a域的值,如果为真则不管。

1.8 int

  根据a域的值,在活动记录表中初始化几个变量的值。

int action1[200];
int moveId = 0;
int backId = 0;
int staticId = 0;
int actId = 0;
void explainToPerfrom()//目标代码的解释执行
{
	for (int i = 0; i < tableId; i++)
	{
		if (table[i].kind == "var")
		{
			vartable[vartableid].name = table[i].name;
			vartable[vartableid].value = 0;
		}
		vartableid++;
	}
	stack com;//运算栈
	stack actStack;//活动记录栈
	int temp = 0;//用户输入
	int cid = 0;//代码数组下标
	int tempCount = 0;//暂时保存
	int tempCode = 0;
	int tempBackId = 0;
	int tempMoveId = 0;
	int tempStaticId = 0;
	int lev = 0;//当前层数
	while (cid != codeId-1) 
	{
		if (code[cid].funcCode == "jmp")//跳转语句
		{
			if (cid == 0)//初始的入栈
			{
				action1[actId] =0;
				moveId = 0;//当前动态链
				backId = 1;
				staticId = 2;
				actId++;
				action1[actId] = 0;
				actId++;
				action1[actId] = 0;
				actId++;
			}
			cid = code[cid].displacement;
			
		}
	  else if (code[cid].funcCode == "opr")//运算语句
	  {
		  switch (code[cid].displacement)
		  {
		    case 0://退出过程
			{
				cid = action1[backId];
				actId = moveId;
				moveId = action1[moveId];
				backId = moveId+1;
				staticId =moveId+2;
				cid--;
				break;
			}
		    case 1://加法运算
				tempCount = com.top();
				com.pop();
				tempCount = tempCount + com.top();
				com.pop();
				com.push(tempCount);
				break;
			case 2://减法运算
				tempCount = com.top();
				com.pop();
				tempCount = com.top()-tempCount;
				com.pop();
				com.push(tempCount);
				break;
			case 3://乘法运算
				tempCount = com.top();
				com.pop();
				tempCount = com.top()*tempCount;
				com.pop();
				com.push(tempCount);
				break;
			case 4://除法运算
				tempCount = com.top();
				com.pop();
				tempCount = com.top()/tempCount;
				com.pop();
				com.push(tempCount);
				break;
			case 5://等于判断
				tempCount = com.top();
				com.pop();
				if (tempCount == com.top())
					tempCount = 1;
				else
					tempCount = 0;
				com.pop();
				com.push(tempCount);
				break;
			case 6://不等号运算
				tempCount = com.top();
				com.pop();
				if (tempCount == com.top())
					tempCount = 0;
				else
					tempCount = 1;
				com.pop();
				com.push(tempCount);
				break;
			case 7://小于
				tempCount = com.top();
				com.pop();
				if (com.top() < tempCount)
					tempCount = 1;
				else
					tempCount = 0;
				com.pop();
				com.push(tempCount);
				break;
			case 22://判断是否为奇数
				if (com.top() % 2 == 1)
					tempCount = 1;
				else
					tempCount = 0;
				com.pop();
				com.push(tempCount);
				break;
			case 28://输入
				cout << "请输入:";
				cin >> temp;
				//vartable[vartableid].
				com.push(temp);
				break;
			case 29://输出
				cout << com.top()<<"\n";
				break;
		  }
		  cid++;
	  }
	  else if (code[cid].funcCode == "lit")//常量声明
	  {
		  com.push(code[cid].displacement);
		  cid++;
	  }
	  else if (code[cid].funcCode == "lod")//加载变量
	  {  
		  //string tempName = findSymble(code[cid].displacement);
		  //com.push(findVar(tempName));
		  int tempId = 0;
		  if (code[cid].levelDiff == 0)
			  tempId = moveId;
		  else
		  {
			  tempId = staticId;
			  for (int i = 0; i < code[cid].levelDiff; i++)
			  {

				  tempId = action1[tempId];
			  }
		  }
		  com.push(action1[tempId + code[cid].displacement]);
		  cid++;
	  }
	  else if (code[cid].funcCode == "sto")//将栈顶结果送给变量
	  {
		  //string tempName = findSymble(code[cid].displacement);
		  //tempCount = findVar(tempName);
		  //changeVar(tempName,com.top());
		  int tempId = 0;
		  if(code[cid].levelDiff==0)
			   tempId = moveId;
		  else
		  { 
			   tempId = staticId;
			  for (int i = 0; i < code[cid].levelDiff; i++)
			  {
				  tempId = action1[tempId];
			  }
		  }
		  action1[tempId + code[cid].displacement] = com.top();
		  cid++;
	  }
	  else if (code[cid].funcCode == "cal")//过程调用语句
	  {
		  // lev = findSymbleAddr(code[cid].displacement);//更新层次
		  action1[actId] = moveId;
		  tempMoveId = moveId;
		  moveId = actId;
		  actId++;
		  action1[actId] = cid + 1;//修改返回地址
		  tempBackId = backId;
		  backId = actId;
		  actId++;

		  if (code[cid].levelDiff == 0)//层差为0
		  {
			  tempStaticId = staticId;
			  action1[actId] = action1[tempMoveId];//新的静态链
			  staticId = actId;
			  actId++;
		  }
		  if (code[cid].levelDiff == 1)//层差为1
		  {
			  tempStaticId = staticId;
			  tempCount = staticId;
			  //tempCount= action1[tempCount];
			  action1[actId] = action1[tempCount];//新的静态链
			  staticId = actId;
			  actId++;
		  } 
		  cid = code[cid].displacement;
	  }
	  else if (code[cid].funcCode == "jpc")//非真跳转语句
	  {
		  if (com.top() == 0)
			  cid = code[cid].displacement;
		  else
			  cid++;
	  }
	  else if (code[cid].funcCode == "int")//开辟空间
	  {
		  for (int i = 0; i < code[cid].displacement - 3; i++)//变量表初始化
		  {
			  action1[actId] = 0;
			  actId++;
		  }
		  cid++;
	  }
	}
}

 

上面就是解释执行的代码,只需要调用explainToPerform()这个函数就行,不过前提是你有目标代码,前面的代码也在我之前的博客中。到此为止,其他文法的代码已经能跑起来了。

 

你可能感兴趣的:(编译原理)