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

📄 pass1.cpp

📁 虚拟机设计与实现——C/C++
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                   +
+ pass1.c - process directives to build symbol table				+
+                                                                   +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ macros                                                            +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*#define PASS1_DEBUG		1*/

#ifdef	PASS1_DEBUG
#define	PASS1_DEBUG0(arg);						printf(arg);
#define PASS1_DEBUG1(arg1,arg2);				printf(arg1,arg2);
#define PASS1_DEBUG2(arg1,arg2,arg3);			printf(arg1,arg2,arg3);
#else
#define	PASS1_DEBUG0(arg);
#define PASS1_DEBUG1(arg1,arg2);
#define PASS1_DEBUG2(arg1,arg2,arg3);
#endif

#define OUTSIDE_PROC_PASS1	-1

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ declaration                                                       +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

class Pass1
{
	StringTable *strTbl;	/*pointers to symbol repository structures*/
	SymbolTable *symTbl;
	HashTable *hashTbl;

	U4 currentProcPass1;	/*index into symTbl of current procedure*/
	U8 bytePosPass1;		/*current index of bytecode being generated*/
	U8 globalTotal;			/*current total size of globals*/

	void  processDirective(struct Token *tptr, LineTokenizer *ptr);
	void  processGDirective(struct Token *tptr, LineTokenizer *ptr);
	void  processPDirective(struct Token *tptr, LineTokenizer *ptr);

	void  processInstruction(struct Token *tptr);

	public:
	Pass1(StringTable *st, SymbolTable *syt, HashTable *ht);
	void parseLine(struct Line *line);
};

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ definitions                                                       +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

Pass1::Pass1(StringTable *st, SymbolTable *syt, HashTable *ht)
{ 
	strTbl = st;
	symTbl = syt;
	hashTbl = ht;

	currentProcPass1 = OUTSIDE_PROC_PASS1;
	bytePosPass1 = 0;
	globalTotal = 0;
	return;

}/*end constructor*/

/*-----------------------------------------------------------------*/

void Pass1::parseLine(struct Line *line)
{
	struct Token token;
	PASS1_DEBUG2("Pass1::parseLine(): line->(%d)\t text->(%s)\n",(*line).line,(*line).src);

	/*
	line can be
		i) a directive ( starts with a period, i.e.  .IP )
		ii) an instruction ( opcode operand(s) )
		iii) a comment ( starts with # )
	*/
	
	LineTokenizer toker(line);
	token = toker.getNextLineToken();

	if(token.type==TOK_NO_MORE){ return; }

	switch(token.text[0])
	{
		case '.' :{ processDirective(&token,&toker); }break;
		case '#' :{ /*comment, ignore line*/ }break;
		default:{ processInstruction(&token); }
	}
	return;

}/*end parseLine*/

/*-----------------------------------------------------------------*/

/*
	Directives:
	.GB identifier  [ integer ]		define global variable
	( same for .GW, .GD, .GQ )
	.PB	identifier					procedure begin
		.PR identifier +n				procedure return value
		.PA identifier +n				procedure argument
		.PV identifier -n				procedure local variable
		.PL identifier					procedure label
	.PE								procedure end
*/

void  Pass1::processDirective(struct Token *tptr, LineTokenizer *ptr)
{
	if((*tptr).type==TOK_IDENTIFIER)
	{
		switch((*tptr).text[1])
		{
			case 'G':{ processGDirective(tptr,ptr); }break;
			case 'P':{ processPDirective(tptr,ptr); }break;
			default:
			{
				ERROR2("Pass1::processDirective(): %s not directive, line %lu\n",(*tptr).text,(*tptr).line);
			}
		}
	}
	else
	{
		ERROR2("Pass1::processDirective(): %s not directive, line %lu\n",(*tptr).text,(*tptr).line);
	}
	return;

}/*end processDirective*/

/*-----------------------------------------------------------------*/

/*
.GB identifier  [ integer ]	define global variable
	( same for .GW, .GD, .GQ )
*/

void  Pass1::processGDirective(struct Token *tptr, LineTokenizer *ptr)
{
	struct Token t;
	struct HashTbl *hptr; /*returned from hash table*/
	U1 bret;

	/*global variable metadata*/
	char id[ID_SIZE];
	U1 dtype;
	U8 length;
	U8 size;
	U8 offset;
	U4 line;

	switch((*tptr).text[2]) /*.GB identifier  [ integer ]*/
	{
		/*third char, text[2], gives datatype*/

		case 'B':{ dtype = SZ_BYTE; }break;
		case 'W':{ dtype = SZ_WORD; }break;
		case 'D':{ dtype = SZ_DWORD; }break;
		case 'Q':{ dtype = SZ_QWORD; }break;
		default:
		{
			ERROR2("Pass1::processGDirective(): line %d, invalid global data type (%s)\n",(*tptr).line,(*tptr).text);
			return;
		}
	}

	/*set some defaults*/

	length = 1;
	size = dtype*length; 
	offset = 0;
	line = (*tptr).line;

	bret = (*ptr).match(&t,TOK_IDENTIFIER);
	if(bret!=TRUE)
	{ 
		ERROR1("Pass1::processGDirective(): line %d, global missing identifier\n",(*tptr).line);
		return; 
	}

	strcpy(id,t.text);

	PASS1_DEBUG2("Pass1::processGDirective(): .GX %s=%s\n",TokStr[t.type],t.text);
		
	/*
	the [integer] modifiers is optional
	so we cannot use match() because there are 2 correct ways
	
	i)	 .GX identifier integer EOL
	ii)  .GX identifier EOL
	*/

	t = (*ptr).getNextLineToken();

	/* .GX identifier integer EOL */

	if(t.type==TOK_INT_CONST)
	{
		PASS1_DEBUG2("Pass1::processGDirective(): nElements %s=%lu\n",TokStr[t.type],t.val);
			
		length = (U8)t.val;
		size = dtype*length;

		globalTotal = globalTotal + size;
		offset = globalTotal;

		bret = (*ptr).match(&t,TOK_NO_MORE);
		if(bret==FALSE)
		{ 
			ERROR1("Pass1::processGDirective(): line %d, bad global declaration\n",(*tptr).line);
			return; 
		}
	}

	/*.GX identifier EOL*/

	else if(t.type==TOK_NO_MORE)
	{
		size = dtype;
		globalTotal = globalTotal + size;
		offset = globalTotal;
	}

	/*.GX identifer XXXX */

	else 
	{ 
		ERROR1("Pass1::processGDirective(): line %d, bad global declaration\n",(*tptr).line);
		return; 
	}
	

	/*if evade all errors, add .GB entry*/

	PASS1_DEBUG0("Pass1::processGDirective(): adding .GX to symbol table\n");
	hptr =  (*hashTbl).queryHashTbl(id);
	if(hptr!=NULL)
	{
		ERROR2("Pass1::processGDirective(): line %d, %s re-defined\n",line,id);
		return;
	}
	else
	{
		struct GlobalVariable gv;
		gv.text = (*strTbl).iStr;
		gv.dType = dtype;
		gv.len = length;
		gv.size = size;
		gv.offset = offset;
		gv.line= line;
		(*strTbl).addStrTbl(id);
		(*symTbl).addGlobVar(&gv);
		(*hashTbl).addHashTblEntry(id,gv.text,GLOBAL_VAR,((*symTbl).iGlobVar-1),0,line);
	}
	return;

}/*end processGDirective*/

/*-----------------------------------------------------------------*/

/*
	.PB	identifier 				procedure begin
		.PR identifier +n			procedure return value
		.PA identifier +n			procedure argument
		.PV identifier -n			procedure local variable
		.PL identifier				procedure label
	.PE							procedure end
*/

void  Pass1::processPDirective(struct Token *tptr, LineTokenizer *ptr)
{
	struct Token t;
	U1 bret;

	if(strcmp((*tptr).text,".PB")==0)  /*.PB	identifier EOL*/
	{
		char id[ID_SIZE];
		U8 address;
		U4 line;
		struct HashTbl *hptr;

		/*set some defaults*/
		address = 0;
		line  = 0;

		bret = (*ptr).match(&t,TOK_IDENTIFIER);
		if(bret!=TRUE)
		{
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return; 
		}
		
		strcpy(id,t.text);
		line = t.line;
		address = bytePosPass1;

		PASS1_DEBUG2("Pass1::processPDirective(): .PB identifier %s=%s\n",TokStr[t.type],t.text);

		bret = (*ptr).match(&t,TOK_NO_MORE);
		if(bret==FALSE)
		{ 
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return; 
		}	
		
		PASS1_DEBUG0("Pass1::processPDirective(): adding .PB to symbol table\n");

		hptr =  (*hashTbl).queryHashTbl(id);

		if(hptr!=NULL)
		{
			ERROR2("Pass1::processPDirective(): line %d, %s re-definition\n",line,id);
			return;
		}
		else if(currentProcPass1!=OUTSIDE_PROC_PASS1)
		{
			ERROR2("Pass1::processPDirective(): line %d, %s, cannot nest procedures\n",line,id);
			return;
		}
		else
		{
			struct Procedure p;
			p.text = (*strTbl).iStr;
			p.address = address;
			p.line= line;
			(*strTbl).addStrTbl(id);
			(*symTbl).addProc(&p);
			(*hashTbl).addHashTblEntry(id,p.text,PROC,((*symTbl).iProc-1),0,line);
			currentProcPass1 = (*symTbl).iProc-1;
		}

	}/*end .PB*/
	else if(strcmp((*tptr).text,".PR")==0)	/*.PR identifier +n	*/
	{
		char name[ID_SIZE];
		S4 offset;
		U4 line;
		struct HashTbl *hptr;

		line = (*tptr).line;

		bret = (*ptr).match(&t,TOK_IDENTIFIER);
		if(bret!=TRUE)
		{
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return;

		}

		strcpy(name,t.text);

		bret = (*ptr).match(&t,TOK_INT_CONST);
		if(bret!=TRUE)
		{
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return;
		}

		offset = (S4)t.val;

		bret = (*ptr).match(&t,TOK_NO_MORE);
		if(bret!=TRUE)
		{ 
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return; 
		}
			
		PASS1_DEBUG0("processPDirective(): adding .PR to symbol table\n");

		hptr =  (*hashTbl).queryHashTbl(name);
		if(hptr!=NULL)
		{
			ERROR2("processPDirective(): line %d, %s re-defined\n",line,name);
			return;
		}
		else
		{
			struct StackFrame sf;
			sf.text = (*strTbl).iStr;
			sf.fpOffset = offset;
			sf.line = line;
			(*strTbl).addStrTbl(name);
			(*symTbl).setProcRetHL(&sf);
			(*hashTbl).addHashTblEntry(name,sf.text,PROC_RET,((*symTbl).iProc-1),0,line);
		}

	}/*end .PR*/
	else if(strcmp((*tptr).text,".PA")==0)	/*.PA identifier +n*/
	{
		char name[ID_SIZE];
		S4 offset;
		U4 line;
		struct HashTbl *hptr;

		bret = (*ptr).match(&t,TOK_IDENTIFIER);
		if(bret!=TRUE)
		{
			ERROR1("Pass1::processPDirective(): line %lu, bad directive\n",(*tptr).line);
			return;

		}

		strcpy(name,t.text);
		line = t.line;

		bret = (*ptr).match(&t,TOK_INT_CONST);
		if(bret!=TRUE)

⌨️ 快捷键说明

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