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

📄 compiler.cpp

📁 编译原理的作业 编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "compiler.h"

FILE* Compiler::_outExe = NULL;

Compiler::Compiler()
:_cerrs(0), _maxError(50), _listFile(FileList::GetInstance())
{
	_outExe = fopen("source.exf", "wb");
	_dumpFile = fopen("List.txt", "w");
}

Compiler::~Compiler()
{
	fclose(_outExe);
	fclose(_dumpFile);
}

void Compiler::Compile(File& file)
{
	file.GetLine(_curLine);
	Lexer lexer(file, _curLine);
	_lexer = &lexer;
	Program();
	CodeGen();
}

void Compiler::Program()
{
	_lexer ->GetNextToken(_tok);
	while (_tok.type != TOK_EOF)		//should see EOF after Functions; 
	{									//Program Consists of Functions;
		Function();
		_lexer ->GetNextToken(_tok);
	}

	_fileHeader._nMethods = _metaData._methods.Size();
	_fileHeader._nFields = _metaData._fields.Size();
	_fileHeader._cbinstr = _instrs.Size();
	_fileHeader._cbStrPool = _strPool.Size();
}

void Compiler::Function()
{
	Attribute();
	_curMethod._retType = Type();
	FunctionName();
	ArgumentList();
	if (!Lexer::Match(_lexer ->GetNextToken(), TOK_LP_B))
	{
		OutputError(_curLine, ER_ELF0014);
	}
	_metaData.AddMethod(_curMethod);
	_curMethod._isEntry = false;
	_curMethod._retType = Void;
	_curMethod._params.Clear();
	//Method should be added here because the address of the method 
	//Will increase in ILEmit preparing for the next method;
	ILEmit();
	if (!Lexer::Match(_lexer ->GetNextToken(), TOK_RP_B))
	{
		OutputError(_curLine, ER_ELF0015);
	}
}

//Attribute*, should be aware that if there is no attribute with the Method,
//the token is passed along to the next phase, otherwise, the next token is passed
//to the next phase. This is true for all eps closure parsing.
void Compiler::Attribute()
{
	if (Lexer::Match(_tok, TOK_DIRECTIVE))
	{
		if (strcmp(_tok.text, "entry") == 0)
		{
			_curMethod._isEntry = true;
		}
		else
		{
			//TODO: To be added;
		}
		_lexer ->GetNextToken(_tok);
	}
}

ValueType Compiler::Type()
{
	Token tok = _tok;

	if (Lexer::Match(_tok, TOK_KEYWORD))
	{
		_lexer ->GetNextToken(_tok);

		if (strcmp(tok.text, "void") == 0)
		{
			return  Void;
		}
		else if (strcmp(tok.text, "s8") == 0)
		{
			return  Int8;
		}
		else if (strcmp(tok.text, "u8") == 0)
		{
			return  UInt8;
		}
		else if (strcmp(tok.text, "s16") == 0)
		{
			return  Int16;
		}
		else if (strcmp(tok.text, "u16") == 0)
		{
			return  UInt16;
		}
		else if (strcmp(tok.text, "s32") == 0)
		{
			return  Int32;
		}
		else if (strcmp(tok.text, "u32") == 0)
		{
			return  UInt32;
		}
		else if (strcmp(tok.text, "s64") == 0)
		{
			return  Int64;
		}
		else if (strcmp(tok.text, "u64") == 0)
		{
			return  UInt64;
		}
		else if (strcmp(tok.text, "f32") == 0)
		{
			return  Float32;
		}
		else if (strcmp(tok.text, "f64") == 0)
		{
			return  Float64;
		}
		else
		{
			OutputError(_curLine, ER_ELF0016);
			return Void;
		}
	}
	return Void;
}

int Compiler::Identifier()
{
	if (Lexer::Match(_tok, TOK_IDENTIFIER))
	{
		return _strPool.Add(_tok.text);
	}
	return -1; 
}

void Compiler::FunctionName()
{
	int i = Identifier();
	if (i != -1)
	{
		_curMethod._name = i;
	}
	else
	{
		OutputError(_curLine, ER_ELF0008);
	}
}

void Compiler::Argument()
{
	_curField._type = Type();
	if (_curField._type == Void)
	{
		OutputError(_curLine, ER_ELF0018);
	}

	int i = Identifier();
	if (i != -1)
	{
		_curField._name = i;
	}
	else
	{
		OutputError(_curLine, ER_ELF0019);
	}
}

void Compiler::ArgumentList()
{
	if (!Lexer::Match(_lexer ->GetNextToken(), TOK_LP_S))
	{
		OutputError(_curLine, ER_ELF0010);  
	}

	_lexer ->GetNextToken(_tok);
	if (Lexer::Match(_tok, TOK_RP_S))
	{
		return;
	}
	
	while (true)
	{
		Argument();
		_metaData._fields.PushBack(_curField);
		_curMethod._params.PushBack(_metaData._fields.Size() - 1);
		_lexer ->GetNextToken(_tok);

		if (!Lexer::Match(_tok, TOK_COMMA))
		{
			break;
		}
		_lexer ->GetNextToken(_tok);

		if (Lexer::Match(_tok, TOK_RP_S))
		{
			OutputError(_curLine, ER_ELF0023);
			return;					//For continue compiling;
		}
	}

	if (Lexer::Match(_tok, TOK_RP_S))
	{
		return;
	}
	else
	{
		OutputError(_curLine, ER_ELF0017);
	}
}

void Compiler::ILEmit()
{
	int errorNo = -1;
	Instr instr;
	bool eoi = false;

	while (!eoi)
	{
		_lexer ->GetNextToken(_tok);
		if (_tok.type == TOK_EOF)
		{
			return;
		}

		if (_tok.type == TOK_IDENTIFIER)
		{
			switch (_tok.text[0])
			{
			case 'a':
				if (strcmp(_tok.text, "add") == 0)
				{
					instr.opcode = ADD;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else if (strcmp(_tok.text, "and") == 0)
				{
					instr.opcode = AND;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'b':
				if (strcmp(_tok.text, "brk") == 0)
				{
					instr.opcode = BRK;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'c':
				if (strcmp(_tok.text, "call") == 0)
				{
					instr.opcode = CALL;
					errorNo = ILCallArgumentList();
					instr.arg = _curMethod._addr;
					_instrs.PushBack(instr);
				}
				else if (strcmp(_tok.text, "ceq") == 0)
				{
					instr.opcode = CEQ;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else if (strcmp(_tok.text, "conv.f") == 0)
				{
					instr.opcode = CONV_F;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else if (strcmp(_tok.text, "cpblk") == 0)
				{
					instr.opcode = CPBLK;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'd':
				if (strcmp(_tok.text, "div") == 0)
				{
					instr.opcode = DIV;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else if (strcmp(_tok.text, "dup") == 0)
				{
					instr.opcode = DUP;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'h':
				if (strcmp(_tok.text, "halt") == 0)
				{
					instr.opcode = HALT;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'j':
				if (strcmp(_tok.text, "jmp") == 0)
				{
					instr.opcode = JMP;
					_instrs.PushBack(instr); 
					_curMethod._addr += 2;
				}
				else
				{
					errorNo = ER_ELF0001;
				}
				break;
			case 'l':
				if (strcmp(_tok.text, "ldc") == 0)
				{
					instr.opcode = LDC;
					instr.hasArg = true;
					_lexer ->GetNextToken(_tok);

					if (_lexer ->Match(_tok, TOK_INT_CONST))
					{
						instr.arg = _tok.arg;
						_instrs.PushBack(instr); 
						_curMethod._addr += 10;
					}
					else
					{
						errorNo = ER_ELF0001;
					}

				}
				else if (strcmp(_tok.text, "ldc.s") == 0)
				{
					instr.hasArg = true;
					instr.opcode = LDC_S;
					_lexer ->GetNextToken(_tok);

					if (_lexer ->Match(_tok, TOK_INT_CONST))
					{
						if (_tok.arg > 127)
						{
							errorNo = ER_ELF0003;
						}
						else
						{
							instr.arg = _tok.arg;
							_instrs.PushBack(instr); 
							_curMethod._addr += 10;
						}

					}
					else
					{
						errorNo = ER_ELF0001;
					}
				}
				else if (strcmp(_tok.text, "ldstr") == 0)
				{
					instr.hasArg = true;
					instr.opcode = LDSTR;
					_lexer ->GetNextToken(_tok);

					if (_lexer ->Match(_tok, TOK_STR_CONST))
					{
						instr.hasArg = true;
						instr.arg = _strPool.Add(_tok.text); 
						_instrs.PushBack(instr); 
						_curMethod._addr += 10;
					}
					else
					{
						errorNo = ER_ELF0004;

					}
				}
				else
				{
					errorNo = ER_ELF0001;

⌨️ 快捷键说明

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