Created
November 20, 2012 05:40
-
-
Save bencz/4116247 to your computer and use it in GitHub Desktop.
Basic compiler, generate IL CODE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
INPUT SAMPLE: | |
VAR NUMBER = 25 | |
VAR STRING = "ALEX" | |
VAR ERRO = "THAT's NOT CAUSE AN ERROR :)" | |
PRINT ERRO | |
PRINT "ALEXANDRE" | |
PRINT NUMBER | |
GETLINE | |
*/ | |
#include <stdio.h> | |
#include <string> | |
#include <vector> | |
#include <map> | |
#include <Windows.h> | |
using namespace std; | |
bool compile(FILE *fp); | |
bool CodeGen(std::vector<string> tokens); | |
void GenPrint(std::vector<string> tokens, int _pos, bool IsVar, bool _type); | |
void GenVar(std::vector<string> tokens, std::map<string, string> _varInfo, int _pos, bool _varType); | |
void GenGet(); | |
//Assembly code global | |
string AssemblyCode = ""; | |
// Il infs | |
void GenIlHeader(string IlName, FILE* fp); | |
// variable system | |
string VariableNames = ""; | |
string VariableAssembly = ""; | |
int VarNumbersArray = 0; | |
std::string _itoa_(int value, unsigned int base); | |
int main() | |
{ | |
char *filename = "test.in"; | |
FILE *fp = fopen(filename, "rb"); | |
if(!fp) | |
{ | |
return 1; | |
} | |
if(!compile(fp)) | |
{ | |
printf("ERROR...\n"); | |
} | |
fclose(fp); | |
FILE* fpw = fopen("test.il", "wb"); | |
if(!fpw) | |
return 1; | |
GenIlHeader("test", fpw); | |
// Write the variable declarations | |
fprintf(fpw, "\t.locals init (\n"); | |
VariableNames[VariableNames.length()-2] = ')'; // remove the last comma | |
fwrite(VariableNames.c_str(), VariableNames.length(), 1, fpw); | |
// Write the code | |
fwrite(VariableAssembly.c_str(), VariableAssembly.length(), 1, fpw); // write variables | |
fwrite(AssemblyCode.c_str(), AssemblyCode.length(), 1, fpw); // write code | |
fprintf(fpw, "\tret\n"); | |
fprintf(fpw, "}"); | |
fclose(fpw); | |
} | |
bool compile(FILE *fp) | |
{ | |
char c; | |
string token; | |
std::vector<string> tokens; | |
bool _return = true; | |
bool InQuote = false; | |
while ((c = getc(fp)) != EOF) | |
{ | |
if(InQuote) | |
{ | |
token += c; | |
if(c == '"') | |
InQuote = false; | |
} | |
else if(isalpha(c) || isalnum(c) || c == '"' || c == '=') | |
{ | |
if(c == '"') | |
InQuote = true; | |
token += c; | |
} | |
else if(c == ' ' || c == '\0' || c == '\n') | |
{ | |
tokens.push_back(token); | |
token = ""; | |
} | |
} | |
tokens.push_back(token); | |
if(!CodeGen(tokens)) | |
_return = false; | |
return _return; | |
} | |
bool CodeGen(std::vector<string> tokens) | |
{ | |
int i; | |
bool _IsVar = false; | |
bool _varType = false; // false -> INT && true -> string | |
bool _type = false; // false -> INT && true -> string | |
bool _return = true; | |
map<string, string> _varInfo; | |
for(i=0;i<tokens.size();i++) | |
{ | |
if(tokens[i] == "PRINT") | |
{ | |
if(tokens[i+1][0] == '"') | |
{ | |
_IsVar = false; | |
_type = true; // string | |
} | |
else | |
{ | |
// get the variable type | |
map<string, string>::iterator it = _varInfo.find(tokens[i+1]); | |
if(it != _varInfo.end()) | |
{ | |
if(it->second[0] == '"') | |
{ | |
_IsVar = true; | |
_type = true; | |
} | |
else | |
{ | |
_IsVar = true; | |
_type = false; // int | |
} | |
} | |
} | |
GenPrint(tokens, i, _IsVar, _type); | |
} | |
else if(tokens[i] == "VAR") | |
{ | |
if(tokens[i+2] != "=") | |
{ | |
printf("Error... faltou o = \n"); | |
_return = false; | |
} | |
else | |
{ | |
// get var type ( int or string ) | |
if(isalnum(tokens[i+3][0])) // int | |
{ | |
_varInfo.insert(make_pair(tokens[i+1], tokens[i+3])); | |
_varType = false; | |
} | |
else if(tokens[i+3][0] == '"') // string | |
{ | |
_varInfo.insert(make_pair(tokens[i+1], tokens[i+3])); | |
_varType = true; | |
} | |
} | |
GenVar(tokens, _varInfo, i, _varType); | |
} | |
else if(tokens[i] == "GETLINE") | |
{ | |
GenGet(); | |
} | |
} | |
return _return; | |
} | |
// ++++++++++++++++++++ // | |
// The code gen section // | |
// ++++++++++++++++++++ // | |
void GenPrint(std::vector<string> tokens, int _pos, bool IsVar, bool _type) | |
{ | |
if(IsVar) | |
{ | |
if(_type) // string | |
{ | |
AssemblyCode += "\tldloc "; | |
AssemblyCode += tokens[_pos+1].c_str(); | |
AssemblyCode += "\n\tcall void [mscorlib]System.Console::WriteLine(string)\n"; | |
} | |
else // int | |
{ | |
AssemblyCode += "\tldloca.s "; | |
AssemblyCode += tokens[_pos+1].c_str(); | |
AssemblyCode += "\n\tcall instance string [mscorlib]System.Int32::ToString()\n"; | |
AssemblyCode += "\tcall void [mscorlib]System.Console::WriteLine(string)\n"; | |
} | |
} | |
else | |
{ | |
AssemblyCode += "\tldstr "; | |
AssemblyCode += tokens[_pos+1].c_str(); | |
AssemblyCode += "\n"; | |
AssemblyCode += "\tcall void [mscorlib]System.Console::WriteLine(string)\n"; | |
} | |
} | |
void GenVar(std::vector<string> tokens, std::map<string, string> _varInfo, int _pos, bool _varType) | |
{ | |
string buildBase = ""; | |
map<string, string>::iterator it = _varInfo.find(tokens[_pos+1]); | |
if(it != _varInfo.end()) | |
{ | |
if(_varType == true) // string | |
{ | |
string number = _itoa_(VarNumbersArray, 10); | |
string declaration = "\t\t[" + number + "] string " + it->first.c_str() + ",\n"; | |
VariableNames += declaration; | |
buildBase += "\tldstr "; | |
buildBase += it->second.c_str(); | |
buildBase += "\n"; | |
VariableAssembly += buildBase; | |
// Clear buildbase | |
buildBase = ""; | |
buildBase += "\tstloc "; | |
buildBase += it->first.c_str(); | |
buildBase += "\n"; | |
VariableAssembly += buildBase; | |
VarNumbersArray++; | |
} | |
else // int | |
{ | |
string number = _itoa_(VarNumbersArray, 10); | |
string declaration = "\t\t[" + number + "] int32 " + it->first.c_str() + ",\n"; | |
VariableNames += declaration; | |
buildBase += "\tldc.i4.s "; | |
buildBase += it->second.c_str(); | |
buildBase += "\n"; | |
VariableAssembly += buildBase; | |
// clear buildBase | |
buildBase = ""; | |
buildBase += "\tstloc "; | |
buildBase += it->first.c_str(); | |
buildBase += "\n"; | |
VariableAssembly += buildBase; | |
VarNumbersArray++; | |
} | |
} | |
} | |
void GenGet() | |
{ | |
AssemblyCode += "\tnop\n"; | |
AssemblyCode += "\tcall string [mscorlib]System.Console::ReadLine()\n"; | |
AssemblyCode += "\tpop\n"; | |
} | |
// ++++++++++++++++++ // | |
// Il basic generator // | |
// ++++++++++++++++++ // | |
void GenIlHeader(string IlName, FILE* fp) | |
{ | |
fprintf(fp, ".assembly %s {}\n", IlName.c_str()); | |
fprintf(fp, ".assembly extern mscorlib {}\n"); | |
fprintf(fp, ".method static void Main()\n"); | |
fprintf(fp, "{\n"); | |
fprintf(fp, "\t.entrypoint\n"); | |
fprintf(fp, "\t.maxstack 1\n\n"); | |
} | |
// ************ // | |
// Special Test // | |
// ************ // | |
std::string _itoa_(int value, unsigned int base) | |
{ | |
const char digitMap[] = "0123456789abcdef"; | |
std::string buf; | |
if (base == 0 || base > 16) | |
{ | |
return buf; | |
} | |
std::string sign; | |
int _value = value; | |
if (_value == 0) | |
return "0"; | |
if (value < 0) | |
{ | |
_value = -value; | |
sign = "-"; | |
} | |
for (int i = 30; _value && i ; --i) | |
{ | |
buf = digitMap[ _value % base ] + buf; | |
_value /= base; | |
} | |
return sign.append(buf); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment