?? compiler.cpp
字號:
#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 + -