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

📄 plxcompiler.cpp

📁 一个PLX教学编译器IDE
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			gen(JMP,0,0);		
			int cx2  = cx -1; 
			
			code[cx1].a = cx;
			
			if(sym == elsesym)
			{
				getsym();
				
				Satement();
				
				code[cx2].a = cx; 
			}
			
			if(sym == endsym)
			{
				getsym();
				code[cx2].a = cx;
				
			}else
			{
				error("if 语句缺乏 end标记符!");
				text(2);
			}
		
        }else
		{   
			error("不可识别的'if'语句内容!");
			text(2);
		}

	}else if(sym == whilesym)
	{
		int cx1 = cx;

	    getsym();
		be();

		int cx2 = cx;

		gen(JPC,0,0);

		if(sym == dosym || textIn(3))
		{
		    if(sym == dosym)
			{
			   getsym();
			}else
			{  
			   error("'while' 语句缺少 'do'标识符!");
			}

            Satement();

			gen(JMP,0,cx1);
			code[cx2].a = cx;
		
			if(sym == endsym)
			{
				getsym();
				
			}else
			{
				error("在 while 循环里需要一个 end 标识符!");
			}

		}else
		{
			error("不可识别的'while'语句内容!");
		    text(2);
		}
		
	}else if(sym == repeasym)
	{
		int cx1 = cx;

	    getsym();

        Satement();

		if(sym == untilsym || textIn(3))
		{
			if(sym == untilsym)
			{  
			   getsym();
			}else
			{
			   error("repeat 缺乏'until'标识符!");
			}

			be();

			gen(JPC,0,cx1); 
		}else
		{
            error("repeat 缺乏'until'标识符!");
		    text(2);		
		}
	
	}else if(sym == writesym)
	{
		getsym();
		ae();

		gen(SHO,0,0);  
	
	}else if(sym == callsym)
	{
	    getsym();

		if(sym == ident)
		{
			int index = position(id);

			if(index == 0)
			{
			   error("%s 没有定义!",id);
			   getsym();

			   text(2);
			}else
			{
               if(table[index].kind != varProc)
			   {
				   error("被调用的不是过程!");
			   }else
			   {
                   gen(CAL,lev-table[index].level,table[index].adr);
			       getsym();
			   }
			}
		}else
		{
		    error("call 语句无法识别!");

			text(2);
		}

	}else
	{
	    /* 空语句 */
	}
}

/* bool 表达式语句 */
void plxCompiler::be()
{
    bt();

	while(sym == orsym)
	{	
		getsym();
		
		bt();
		
        gen(OPR,0,14);
	}
}

/* 数学整形表达式 */
void plxCompiler::ae()
{
	int addop = -1;

    if(sym == minus)
	{
		addop = sym;
	    getsym();
		at();

		gen(OPR,0,1);
	}else
	{
	    at();
	}

	while(sym == minus || sym == plus)
	{			
		addop = sym;
		getsym();
		
		at();
		
		if(addop == plus)
		{
			gen(OPR,0,2);
		}else
		{
			gen(OPR,0,3);
		}
	}
}

/* 数学乘除表达式 */
void plxCompiler::at()
{
    af();

	int mulop = -1;

	while(sym == times || sym == slash || sym == odd)
	{
		mulop = sym;
		getsym();
		
		af();
		
		if(mulop == times)
		{
			gen(OPR,0,4);
			
		}else if(mulop == slash)
		{
			gen(OPR,0,5);
		}else
		{
		    gen(OPR,0,6);
		}
	}
}

/* and 布尔表达式 */
void plxCompiler::bt()
{
    bf();

	while(sym == andsym )
	{	
	    getsym();
		   
		bf();
		gen(OPR,0,15);
	}
}

/* 表达式因子 */
void plxCompiler::af()
{
    if(sym == ident)
	{
	    int index = position(id);

		if(index == 0)
		{
		    error("'%s' 没有定义!",id);
			getsym();
		}else
		{
			int kind  = table[index].kind;
			
			if(kind == varInteger)
			{
				getsym();

		        offset();

				gen(LOD,lev-table[index].level,table[index].adr);
							
			}else if(kind == varConst)
			{
				gen(LIT,0,table[index].val);
				getsym();

			}else
			{
				error("'%s' 运算式中不可使用!",id);
			}
		}
	}else
	{
	    if(sym == lparen)
		{
		    getsym();

			ae();

			if(sym == rparen)
			{
			    getsym();
			}else
			{
			   error("缺乏')'标识符!");
			}
		}else if(sym == number)
		{
			gen(LIT,0,num);
			getsym();
			
		}else
		{
		   error("不可识别的运算因子!");

		   text(2);
		}
	}
}

/* 布尔表达式   */
void plxCompiler::bf()
{
    if(sym == ident)
	{
	    int index = position(id);

		if(index == 0)
		{
		   error("'%s' 标识符未定义!",id);
		   getsym();
		
		}else
		{
		   if(table[index].kind == varLogical)
		   {
			   getsym();

			   offset();

			   gen(LOD,lev-table[index].level,table[index].adr);
		       
		   }else
		   {
		       re();
		   }
		}

	}else if(sym == truesym)
	{
		getsym();
		gen(LIT,0,1);
	    
	}else if(sym == falsesym)
	{
	    getsym();
		gen(LIT,0,0);

	}else if(sym == notsym)
	{
		getsym();
		bf();

		gen(OPR,0,16);
	
	}else if(sym == lparen)
	{
	    getsym();

		be();

		if(sym == rparen)
		{
		    getsym();

		}else
		{
		    error("运算式缺少 ')' 标识符!");
		}

	}else 
	{
	    re();
	}
}

void plxCompiler::re()
{ 
	ae();

	switch(sym)
	{
	case eql : getsym();
		       ae();
		       gen(OPR,0,8);	
		       break;
	case gtr : getsym();
		       ae();
		       gen(OPR,0,12);	
		       break;
	case lss : getsym();
		       ae();
		       gen(OPR,0,10);	
		       break;
	case geq : getsym();
		       ae();
		       gen(OPR,0,11);	
		       break;
	case leq : getsym();
		       ae();
		       gen(OPR,0,13);	
		       break;
	case neql: getsym();
		       ae();
		       gen(OPR,0,9);	
		       break;
	default  : error("错误的运算符号!");		
	}
}

/* 生成中间码 */
void plxCompiler::gen(fct _f,int _l,int _a)
{
    if(cx < MAX_CODENUMBER)
	{
	    code[cx].f    = _f;
		code[cx].l    = _l;
		code[cx].a    = _a;
		code[cx].line = codeIndex++;

		if(_f == STO || _f == LOD || _f == LIT )
		{
		   code[cx].lev = lev;
		}else
		{
		   code[cx].lev = -1;
		}

		cx++;

	}else
	{
	   error("程序长度溢出!");
	}
}

/* 跳出错误代码区间 */
void plxCompiler::text(int index)
{ 
	while(!textIn(index))
	{
	    getsym();
	}
}

/* 测试当前sym是否属于跟随集  */
bool plxCompiler::textIn(int index)
{
	FOLLOW temp = non_finis[index];

   	for(int i = 0;i<temp.num ;i++)
	{
	   if(sym == temp.followSym[i])
		   return TRUE;
	}

	return FALSE;
}

/* 清除虚拟机中的代码 */
void plxCompiler::clearStack()
{
	t = 0;
	b = 1;
	p = 0;
	
	s[1] = 0;
	s[2] = 0;
	s[3] = 0;
}

/* 虚拟机 */
int plxCompiler::interpret(int debugStyle)
{	
	CODE  i;   /*  指令寄存器  */
	
	if(debugStyle == RUNBREAKPOINT) clearStack();	

	do{
	    i = code[p];
		p++;

		if(debugStyle == RUNBREAKPOINT)// && i.line > breakpoint && breakpoint != 0)
		{
		    return i.line;		
		}

		switch(i.f)
		{
		case LIT : t++;
			       s[t] = i.a;					   
			       break;
		case OPR : switch(i.a)
				   {
			        case 0: t = b-1;    
				            p = s[t+3]; 
							b = s[t+2];	 			
							break;
			        case 1: s[t] = -s[t];
				            break;
			        case 2: t--;
				            s[t] = s[t] + s[t+1];
				            break;
			        case 3: t--;
				            s[t] = s[t] - s[t+1];
				            break;
			        case 4: t--;
				            s[t] = s[t] * s[t+1];
				            break;
			        case 5: t--;
				            s[t] = s[t] / s[t+1];
				            break;
			        case 6: t--;
						    s[t] = s[t] % s[t+1];
						    break;
			        case 7: break;  
			        case 8: t--;
				            s[t] = (int)(s[t] == s[t+1]);
				            break;
			        case 9: t--;
				            s[t] = (int)(s[t] != s[t+1]);
				            break;  
			        case 10:t--;
				            s[t] = (int)(s[t] < s[t+1]);
				            break;
			        case 11:t--;
				            s[t] = (int)(s[t] >= s[t+1]);
				            break;
			        case 12:t--;
				            s[t] = (int)(s[t] > s[t+1]);
				            break;
			        case 13:t--;
				            s[t] = (int)(s[t] <= s[t+1]);
				            break;  
			        case 14:t--;
				            s[t] = (int)(s[t] | s[t+1]);
				            break;  
			        case 15:t--;
				            s[t] = (int)(s[t] & s[t+1]);
				            break; 
			        case 16:s[t] = (int)(!s[t]);
				            break; 
				   }
			       break;
		case LOD : s[t] = s[base(i.l)+i.a + s[t]];				   
			       break;		
		case STO : t--;
			       s[base(i.l)+i.a + s[t]] = s[t+1];			  
			       ListVariable(i,s[t+1]);		
			       t--;                 
			       break;		
		case CAL : s[t+1] = base(i.l);
			       s[t+2] = b;
				   s[t+3] = p;
				   b = t + 1;
				   p = i.a;			
			       break;		
		case INT : t = t + i.a;
			       break;		
		case JMP : p = i.a;			     
			       break;		   
		case JPC : {CString str;
				   str.Format(_T("%d"),s[t]);				      
                   pOutputView->AddText(str);
				   }
			       if(s[t] == 0)
				   {
				       p = i.a;
				   }
			       t--;
			       break;
		case SHO : {
			           ASSERT_VALID(pOutputView);	
					   
					   CString str;
					   str.Format(_T("%d"),s[t]);				      
                       pOutputView->AddText(str);					   
				   }
			       t--;
				   break;
		default  :;
		}	

        if(debugStyle == RUNINTO)
		{
			showCode(i.line);
		    return i.line;
		}

	}while( p != 0 );

	return -1;
}

/* 计算静态链地址 */
int plxCompiler::base(int l)
{
	int b1 = b;
	int l1 = l;

	while(l1 > 0)
	{
	   b1 = s[b1];
	   l1 = l1 - 1;  
	}

    return b1;
}

/* 错误输出函数*/
void plxCompiler::error(const char *format,...)
{
	char buffer[1024];	
	va_list valist;
	va_start (valist, format);   
	if(_vsnprintf ((char *)buffer,1024,format,valist) == -1)
		return;
	va_end (valist);

    textOut(buffer);
}

/*  错误代码输出    */
void plxCompiler::textOut(char *text)
{
    CString str;
	str.Format(_T("%04d error : %s"),lineIndex,text);

	if(pDebugView->m_hWnd != NULL)
	{	
	    pDebugView->AddText(str,lineIndex);
	}

	errornum++;
}

/* 显示列表变量     */
void plxCompiler::ListVariable(CODE i,int value)
{
    ASSERT_VALID(pVariableView);

    int ix = getTableIndex(i.lev-i.l,i.a);

	if(ix == -1)
		return;

    pVariableView->ChangeValue(table[ix].ldex,value);
}

/* 判断那个table变量是当前改变的变量    */
int plxCompiler::getTableIndex(int lev,int adx)
{
	/* 用1开头是因为table本身是1开始的  */
    for(int i=1;i<=tx;i++)
	{
		/* 加速的方法但是效果不明显,因为速度慢在于设置list  */
	    if(table[i].adr != adx || table[i].level != lev)
		{		   
		    continue;
		}	

		return i;
	}

    return -1;
}
/************************************** 接口 ***********************************************/

/*  打开plx文件 */
bool plxCompiler::OpenFile(const char *fileName)
{
    InFile.open(fileName);

	if(InFile.fail())	
	   return false;

	sourceFilepath = CString(fileName);

	return true;
}

/* 开始编译     */
void plxCompiler::Compiler()
{
    clear();

	getch();
	getsym();

	pDebugView->AddText("Compiling......");
	pDebugView->AddText(sourceFilepath);

    Prog();
	closeResource();
}

/* build        */
bool plxCompiler::Build(LPCTSTR outputfile)
{
    Compiler();  
	
	if(this->GetErrorNumber() != 0)
		return FALSE;

	return outputCode(outputfile);	
}

/* 虚拟机调试   */
void plxCompiler::Debug()
{
	clearStack();
    interpret(RUNBREAKPOINT);
}

/* 获取错误数目 */
int plxCompiler::GetErrorNumber()
{
    return errornum;
}

/* 屏幕上显示中间码 */
void plxCompiler::showCode(int index)
{
	if(pCodeView->m_hWnd == NULL)
		return;
	
	char word[9][4] = {"OPR",
		               "LIT",
					   "LOD",
					   "STO",
					   "INT",
					   "JMP",
					   "JPC",
					   "SHO",
					   "CAL"};
	
	CString codetext;

	pCodeView->SetRedraw(FALSE);
	pCodeView->Clean();

	for(int i=0;i<cx;i++)
	{
        if(index != i)
		   codetext.Format(_T("  %04d: %s %2d %4d"),i,word[code[i].f],code[i].l,code[i].a);
		else
		   codetext.Format(_T("->%04d: %s %2d %4d"),i,word[code[i].f],code[i].l,code[i].a); 
		
		pCodeView->AddText(codetext,index);
	}

    pCodeView->SetRedraw(TRUE);
}

/* 输出中间码到文件 */
bool plxCompiler::outputCode(LPCTSTR outputfile)
{
	ofstream objectOut(outputfile,ios::out);
	
	if(objectOut.fail())
	{
	   return FALSE;
	}

	for(int i=0;i<cx;i++)
	{
		objectOut<<code[i].f<<' '<<code[i].l<<' '<<code[i].a<<'\n';
	}

	return TRUE;
}

/* 设置断点函数 */
bool plxCompiler::SetBreakpointLine(int line)
{
	if(breakpoint == line)
	{
	    breakpoint = 0;	

		return FALSE;
	}else
	{
	    breakpoint = line;	
	}  

	return TRUE;
}

/* 设置Debug信息显示对象 */
void plxCompiler::SetDebugView(COutputView *pDebug)
{
	ASSERT_VALID(pDebug);
    pDebugView = pDebug;
}

/* 设置输出信息显示对象  */
void plxCompiler::SetOutputView(COutputView *pOutView)
{
	ASSERT_VALID(pOutView);
    pOutputView = pOutView;
}

/* 设置中间码显示对象    */
void plxCompiler::SetCodeOutView(COutputView *pCode)
{
	ASSERT_VALID(pCode);
    pCodeView = pCode;
}

/* 设置变量列表          */
void plxCompiler::SetVariableList(CVariableList *pList)
{
	ASSERT_VALID(pList);
    pVariableView = pList;
}

/* 清空重新初始化 */
void plxCompiler::clear()
{
    cc          = 0;
	ll          = 0;
	lineIndex   = 0;
	tx          = 0;                  
	cx          = 0;
    dx          = 0;
    lev         = 0;
	codeIndex   = 0;

	errornum    = 0;
	nDebugStyle = 0;
}

/* 关闭文件流     */
void plxCompiler::closeResource()
{
    InFile.close();
}

/* 获取中间码长度 */
int plxCompiler::GetCodeSize()
{
    return cx;
}

⌨️ 快捷键说明

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