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

📄 analyzer.cpp

📁 C-MINUS编译器
💻 CPP
字号:
#include "Analyzer.h"

// initial the static member here
//-----------------------------------------------------------------------------
symTable Analyzer::symbolTab;
FunArgsCheck Analyzer::FunArgs;
int	Analyzer::location=0;
int	Analyzer::err=0;
int	Analyzer::warn=0;

// constructer
//-----------------------------------------------------------------------------
Analyzer::Analyzer(const string &filename):traceAnalyze(true), traceParse(true)
{
	parse = new Parser(filename);
	program = NULL;
	
	symbolTab.initial();   // because symbolTab and FunArgs is static member,
	FunArgs.initial();     // so, before use , should reset/initial them
	
	symFile = filename;
	int pos = symFile.rfind('.');
	symFile.erase(pos, symFile.length()-1);
	symFile += ".tab";	// symbol table file
    
	is_good_ = true;
	location = 0;      //  intial memory location
	err = 0;           // there are static member, should initial before use
	warn = 0;
}

//-----------------------------------------------------------------------------
Analyzer::~Analyzer()
{
	if (parse)	delete parse;
}

bool Analyzer::is_good() const
{
	return (is_good_ && (err <= 0) && (warn <= 0) && parse->is_good());
}

/**: getSymbolFile
&
* 主要接口,直接用来构造语法树,完成语义分析, 得到结果,
* 即,符号表。
*/
//-----------------------------------------------------------------------------
void Analyzer::getSymbolFile()
{
	outputMsg(-1, "building syntax tree...");
	program = parse->BuildSyntaxTree();

	if (parse->is_good())
	{
       parse->getListFile();
        if (traceParse)	parse->getTreeFile();

		//outputMsg(-1, "successfully build the syntax tree!");
		outputMsg(-1, "constructing symbol table and type cheching...");

		/* 语法树文件可以完全在后面生成,但是总出错, 不得不放在这里,
		* 再加上我调试器坏了,实在没有办法调试了,似乎错误出现在
		* Parser::PrintTree(TreeNode *pNode) 函数中的一条 if 语句,
		* 我没有跟踪内存数据的变化,调试器有问题,,
		* 算了, 放在这里虽然布局比较凌乱,但是还算是效果满意!! 呵呵
		*/
		buildSymtab(program);

		if (is_good())    // if no parse error ..
		{
			//outputMsg(-1, "now, type checking...");
			typeCheck(program);
			if (is_good())  outputMsg(-1, "type check is done, its no error(s)!");
			else		outputMsg(-1, "error(s) occur while type checking!");
		}
		else
		{
			outputMsg(-1, "errors occur while constructing symbol table, stop type checking!");
		}

		if (traceAnalyze && is_good())    // if has no parse and ananlyze error
		{
			//outputMsg(-1, "symbol table complated, printing symbol table file ...");
			symbolTab.printSymTable(symFile);
		} 
	}
	else
	{
		outputMsg(-1, "errors occur while parsing, stop constructing symbol table!");
		err++;        // only list file
        parse->getListFile();
	}
}


/**: buildSymtab(TreeNode *pNode)
&
* Function buildSymtab constructs the symbol 
* table by preorder traversal of the syntax tree
&
* author: lonelyforest.
* data:	 2006.04.08
*/
//-----------------------------------------------------------------------------
void Analyzer::buildSymtab(TreeNode *pNode)
{
	traverse(pNode, insertNode, nullProc);
}


/* Procedure typeCheck performs type checking 
 * by a postorder syntax tree traversal
 */
 //-----------------------------------------------------------------------------
void Analyzer::typeCheck(TreeNode *pNode)
{
	traverse(pNode, nullProc, checkNode);
	if ( symbolTab.lookup("main", "global") == -1)
	{
		err++;
		is_good_ = false;
		outputMsg(-1, "Unresolved external symbol _main");
		warn++;
		outputMsg(-1, "program must have function \"main(void)\" !");
	}
}


/*---------------------------------------------------------------------------*/
void Analyzer::nullProc(TreeNode *pNode)
{
    return;
}
//-----------------------------------------------------------------------------
void Analyzer::traverse(TreeNode *t,
                        void(*preProc)(TreeNode *),
                        void (*postProc)(TreeNode *))
{
    if (t)
    {
        preProc(t);
        for (int i = 0; i < MAX_CHILDREN; ++i)
        {
            traverse( t->child[i], preProc, postProc);
        }
        
        postProc(t);
        traverse( t->sibling, preProc, postProc );
    }
}

//-----------------------------------------------------------------------------
void Analyzer::insertNode(TreeNode *t)
{
	if (!t) return;
	
	switch (t->nodekind ){
		case funK:
			if ( symbolTab.lookup(t->name, t->scope) == -1)
			{
				symbolTab.insert(t->name, t->scope, t->type, t->lineno, location, false);
                addMemLoc();
				FunArgs.insert(t);
			}
			else
			{
				//Analyzer::parse->add_err();
				err++;
				sprintf(msg_temp, "function \"%s\"(...) redefinition", t->name.c_str());
				outputMsg(t->lineno, msg_temp);
			}

			break;
		case varK: 
		case paramK:
			if (symbolTab.lookup(t->name, t->scope) == -1)
			{
				symbolTab.insert(t->name, t->scope, t->type, t->lineno, location, t->bArr);
				addMemLoc();
			}
			else
			{
				err++;
				sprintf(msg_temp, "variable \"%s\" redefinition", t->name.c_str());
				outputMsg(t->lineno, msg_temp);
			}
			break;
		case stmtK:	// just call
			if (t->kind.stmt == callK)
			{
				if (symbolTab.lookup(t->name, t->scope) == -1)
				{
					err++;
					sprintf(msg_temp, "unresolved external symbol \"%s\"", t->name.c_str());
					outputMsg(t->lineno, msg_temp);
				}
				else
				{
					symbolTab.insert(t->name, t->scope, k_ID, t->lineno, 0, false);
				}
			}

			break;
		case expK:
			if (t->kind.exp == IDK) {
				if ( symbolTab.lookup(t->name, t->scope) == -1
					&& symbolTab.lookup(t->name, "global") == -1)
				{	// undeclared
					//Analyzer::parse->add_err();
					err++;
					sprintf(msg_temp, "undeclared identifier: \"%s\"", t->name.c_str());
					outputMsg(t->lineno, msg_temp);
				}
				else if (symbolTab.lookup(t->name, t->scope) !=  -1) 
				{	// local variable
					if( t->father && (t->father->nodekind != stmtK || t->father->kind.stmt != callK)/* not in call statement */ &&
					t->bArr != symbolTab.search_arr(t->name,t->scope)) 
					{	
						//Analyzer::parse->add_err();
						err++;
						sprintf(msg_temp, "\"%s\" is %s declared as array", t->name.c_str(), t->bArr? "not" : "");
						outputMsg(t->lineno, msg_temp);
					}
					else
					{
						symbolTab.insert(t->name, t->scope, t->type, t->lineno, 0, false);
					}
				}
				else
				{	// global variable
					t->scope = "global";
					if( t->father && (t->father->nodekind != stmtK || t->father->kind.stmt != callK)/* not in call statement */ &&
					t->bArr != symbolTab.search_arr(t->name, t->scope) ) {
						//Analyzer::parse->add_err();
						err++;
						sprintf(msg_temp, "\"%s\" is %s declared as array", t->name.c_str(), t->bArr? "not" : "");
						outputMsg(t->lineno, msg_temp);
					}
					else symbolTab.insert(t->name, t->scope, t->type, t->lineno, 0, false);
				}
			}

			break;
		default:
			break;
	}
}



/**: checkNode
&
* author: lonelyforest
* data:	  2006.04.09
*/
//-----------------------------------------------------------------------------
void Analyzer::checkNode(TreeNode *pNode)
{
	TreeNode *t;
    string args;
    int ret, oldline; // record the return value and function defined lineno if its defined.

    // initial them
    ret = oldline = -1;
    args = "";
    t = pNode;

	switch (t->nodekind) {
		case stmtK:
			switch (t->kind.stmt) {
				case readK:
					if (t->child[0]) {
						t->type = t->child[0]->type;
						if (t->type != k_INT){
							outputMsg(t->lineno, "read statement can only read a \"int\" value to a int variable!");
							err++;
						}
					}
					else
					{
						err++;
						outputMsg(-1, "maybe compiler bug!");
					}

					break;
				case writeK:
					if (t->child[0]) {
						t->type = t->child[0]->type;
						if (t->type != k_INT){
							outputMsg(t->lineno, "write statement can only output a \"int\" variable or a number output!");
							err++;
						}
					}
					else
					{
						err++;
						outputMsg(-1, "maybe compiler bug!");
					}

					break;
				case returnK:
					if (t->child[0] == NULL) { // return should be a void
						if (symbolTab.search_type(t->name, "global") != k_VOID) {
							sprintf(msg_temp, " function \"int %s(...)\" must have return value ", t->name.c_str());
							outputMsg(t->lineno, msg_temp);
							err++;
						}
					}
					break;
				case callK:
					ret = FunArgs.check(t, args, oldline);
					if (ret != -3)  // -3 is ok
					{							
						err++;
						warn++;

						if (ret >= 0) {
							sprintf(msg_temp,
                            		"too few or many paramenters to call function \"%s(%s)\", its has %d params",
                                    t->name.c_str(),
                                    args.c_str(),
                                    ret);
							outputMsg(t->lineno, msg_temp);
                            // out put the functions' declaration,
                            sprintf(msg_temp,
                            		"see the function \"%s(%s)\" declaration here!!",
                            		t->name.c_str(),
                                    args.c_str());
                            outputMsg(oldline, msg_temp);

						} else if (ret == -1) {
							sprintf(msg_temp, "function \"%s\"(...) has not declared before use it", t->name.c_str());
							outputMsg(t->lineno, msg_temp);
						} else {
							sprintf(msg_temp,
                            		" call function \"%s(%s)\" with no matched type paramenters!",
                                    t->name.c_str(), args.c_str());
							outputMsg(t->lineno, msg_temp);

                            sprintf(msg_temp,
                            		"see the function \"%s(%s)\" declaration here!!",
                            		t->name.c_str(),
                                    args.c_str());
                            outputMsg(oldline, msg_temp);
						}
					}
					else
					{
						t->type = symbolTab.search_type(t->name, t->scope);
					}
					break;
				default:
					break;
			}
		case expK:
			switch (t->kind.exp) {
				case OpK:
					if (t->type == ASSIGN)
					{
						t->type = t->child[0]->type;
					}
					else
					{
						if (t->child[0]->type == k_VOID || t->child[1]->type == k_VOID)
						{
							err++;
							outputMsg(t->lineno, "illegal use of type \"void\"");
						}
						else if ( t->child[0]->type == k_INT || t->child[1]->type == k_INT)
						{
							t->type = k_INT;
						}
						else
						{
							// ...
						}
					}
					break;
				case IDK:
					t->type = symbolTab.search_type(t->name, t->scope);
					t->bArr = symbolTab.search_arr(t->name, t->scope);
					break;
				default:
					break;
			}
			break;
		default:
			break;
		}
}

⌨️ 快捷键说明

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