mirror of
https://github.com/hazemKrimi/jack-vm-translator.git
synced 2026-05-01 18:00:27 +00:00
chore: scrap old implementation
This commit is contained in:
@@ -1,13 +1,3 @@
|
||||
# Jack Compiler
|
||||
|
||||
This is a compiler made as the an assignment for the [Nand To Tetris Course: Part 2](https://nand2tetris.org/project07). It assumes that the jack file does not have errors for now.
|
||||
|
||||
To compile the program run the following command:
|
||||
```
|
||||
g++ main.cpp -Isrc -std=c++17
|
||||
```
|
||||
To run the executable against jack vm files run the following command with the path of the file:
|
||||
```
|
||||
./a.out <path>
|
||||
```
|
||||
The file will be written next to the source file.
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string translateLabel(string label)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "(" << label << ")" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateGoto(string label)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@" << label << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateIfGoto(string label)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@" << label << endl;
|
||||
output << "D;JNE" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
#include "operations.h"
|
||||
#include "memory.h"
|
||||
#include "branching.h"
|
||||
#include "functions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Code
|
||||
{
|
||||
private:
|
||||
ofstream file;
|
||||
string filename;
|
||||
vector<vector<string>> commands;
|
||||
|
||||
void closeFile()
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
|
||||
public:
|
||||
Code(string path, vector<vector<string>> tokens, bool isNew)
|
||||
{
|
||||
size_t slashIndex = path.find_last_of('/');
|
||||
size_t dotIndex = path.find_last_of('.');
|
||||
|
||||
if (slashIndex != string::npos && dotIndex != string::npos)
|
||||
{
|
||||
filename = path.substr(slashIndex + 1, dotIndex - slashIndex - 1);
|
||||
}
|
||||
|
||||
file = ofstream(path, isNew ? ios_base::out : ios_base::app);
|
||||
commands = tokens;
|
||||
|
||||
if (isNew) {
|
||||
file << "@256" << endl;
|
||||
file << "D=A" << endl;
|
||||
file << "@SP" << endl;
|
||||
file << "M=D" << endl;
|
||||
file << translateCall("Sys.init", 0);
|
||||
}
|
||||
}
|
||||
|
||||
~Code()
|
||||
{
|
||||
closeFile();
|
||||
}
|
||||
|
||||
void translate()
|
||||
{
|
||||
for (const vector<string> &vec : commands)
|
||||
{
|
||||
if (vec.size() == 3)
|
||||
{
|
||||
switch (determineTwoArgumentCommand(vec[0]))
|
||||
{
|
||||
case PUSH:
|
||||
file << translatePush(filename, determineSegment(vec[1]), stoi(vec[2]));
|
||||
break;
|
||||
case FUNCTION:
|
||||
file << translateFunction(vec[1], stoi(vec[2]));
|
||||
break;
|
||||
case CALL:
|
||||
file << translateCall(vec[1], stoi(vec[2]));
|
||||
break;
|
||||
case POP:
|
||||
default:
|
||||
file << translatePop(filename, determineSegment(vec[1]), stoi(vec[2]));
|
||||
}
|
||||
}
|
||||
else if (vec.size() == 2)
|
||||
{
|
||||
switch (determineOneArgumentCommand(vec[0]))
|
||||
{
|
||||
case LABEL:
|
||||
file << translateLabel(vec[1]);
|
||||
break;
|
||||
case GOTO:
|
||||
file << translateGoto(vec[1]);
|
||||
break;
|
||||
case IFGOTO:
|
||||
default:
|
||||
file << translateIfGoto(vec[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (vec.size() == 1)
|
||||
{
|
||||
switch (determineNoArgumentCommand(vec[0]))
|
||||
{
|
||||
case ADD:
|
||||
file << translateAdd();
|
||||
break;
|
||||
case SUB:
|
||||
file << translateSub();
|
||||
break;
|
||||
case NEG:
|
||||
file << translateNeg();
|
||||
break;
|
||||
case EQ:
|
||||
file << translateEq();
|
||||
break;
|
||||
case GT:
|
||||
file << translateGt();
|
||||
break;
|
||||
case LT:
|
||||
file << translateLt();
|
||||
break;
|
||||
case AND:
|
||||
file << translateAnd();
|
||||
break;
|
||||
case OR:
|
||||
file << translateOr();
|
||||
break;
|
||||
case NOT:
|
||||
file << translateNot();
|
||||
break;
|
||||
case RETURN:
|
||||
file << translateReturn();
|
||||
break;
|
||||
default:
|
||||
file << translateNeg();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,182 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int callCounter = 1;
|
||||
|
||||
string translateFunction(string name, int args)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "(" << name << ")" << endl;
|
||||
|
||||
for (int i = 0; i < args; ++i)
|
||||
{
|
||||
output << "@0" << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
}
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateCall(string name, int args)
|
||||
{
|
||||
stringstream output;
|
||||
string label = name + "$ret" + std::to_string(callCounter);
|
||||
|
||||
callCounter++;
|
||||
|
||||
output << "@" << label << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
output << "@LCL" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
output << "@ARG" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
output << "@THIS" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
output << "@THAT" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@C" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@5" << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@C" << endl;
|
||||
output << "M=M-D" << endl;
|
||||
output << "@" << args << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@C" << endl;
|
||||
output << "M=M-D" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@ARG" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@LCL" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@" << name << endl;
|
||||
output << "0;JMP" << endl;
|
||||
output << "(" << label << ")" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateReturn()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@LCL" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@EF" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@RA" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@5" << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@RA" << endl;
|
||||
output << "M=M-D" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@RA" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@ARG" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@ARG" << endl;
|
||||
output << "D=M+1" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@EF" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@1" << endl;
|
||||
output << "D=D-A" << endl;
|
||||
output << "A=D" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@THAT" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@EF" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@2" << endl;
|
||||
output << "D=D-A" << endl;
|
||||
output << "A=D" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@THIS" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@EF" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@3" << endl;
|
||||
output << "D=D-A" << endl;
|
||||
output << "A=D" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@ARG" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@EF" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@4" << endl;
|
||||
output << "D=D-A" << endl;
|
||||
output << "A=D" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@LCL" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@RA" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "D;JMP" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string translatePush(string filename, Segment segment, int index)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
switch (segment)
|
||||
{
|
||||
case LCL:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@LCL" << endl;
|
||||
output << "A=D+M" << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case ARG:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@ARG" << endl;
|
||||
output << "A=D+M" << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case THIS:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@THIS" << endl;
|
||||
output << "A=D+M" << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case THAT:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@THAT" << endl;
|
||||
output << "A=D+M" << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case POINTER:
|
||||
output << (index == 0 ? "@THIS" : "@THAT") << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case STATIC:
|
||||
output << "@" << filename << "." << index << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case TEMP:
|
||||
output << "@" << index + 5 << endl;
|
||||
output << "D=M" << endl;
|
||||
break;
|
||||
case CONSTANT:
|
||||
default:
|
||||
output << '@' << index << endl;
|
||||
output << "D=A" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translatePop(string filename, Segment segment, int index)
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
switch (segment)
|
||||
{
|
||||
case LCL:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@LCL" << endl;
|
||||
output << "D=D+M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case ARG:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@ARG" << endl;
|
||||
output << "D=D+M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case THIS:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@THIS" << endl;
|
||||
output << "D=D+M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case THAT:
|
||||
output << "@" << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@THAT" << endl;
|
||||
output << "D=D+M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case POINTER:
|
||||
output << (index == 0 ? "@THIS" : "@THAT") << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case STATIC:
|
||||
output << "@" << filename << "." << index << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
case TEMP:
|
||||
output << "@" << index + 5 << endl;
|
||||
output << "D=A" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "M=D" << endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@ADDR" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string translateAdd()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@A" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@A" << endl;
|
||||
output << "M=D+M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateSub()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@S" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@S" << endl;
|
||||
output << "M=D-M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateNeg()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@N" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "M=M-D" << endl;
|
||||
output << "M=M-D" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateEq()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
|
||||
string LABEL = generateRandomLabel(8);
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@E" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@E" << endl;
|
||||
output << "M=D-M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@" << LABEL << "_TRUE" << endl;
|
||||
output << "D;JEQ" << endl;
|
||||
output << "@" << LABEL << "_FALSE" << endl;
|
||||
output << "D;JNE" << endl;
|
||||
|
||||
output << "(" << LABEL << "_TRUE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=-1" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << "_FALSE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=0" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << ")" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateGt()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
|
||||
string LABEL = generateRandomLabel(8);
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@GT" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@GT" << endl;
|
||||
output << "M=D-M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@" << LABEL << "_TRUE" << endl;
|
||||
output << "D;JGT" << endl;
|
||||
output << "@" << LABEL << "_FALSE" << endl;
|
||||
output << "D;JLT" << endl;
|
||||
output << "@" << LABEL << "_FALSE" << endl;
|
||||
output << "D;JEQ" << endl;
|
||||
|
||||
output << "(" << LABEL << "_TRUE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=-1" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << "_FALSE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=0" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << ")" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateLt()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
|
||||
string LABEL = generateRandomLabel(8);
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@LT" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@LT" << endl;
|
||||
output << "M=D-M" << endl;
|
||||
output << "D=M" << endl;
|
||||
output << "@" << LABEL << "_TRUE" << endl;
|
||||
output << "D;JLT" << endl;
|
||||
output << "@" << LABEL << "_FALSE" << endl;
|
||||
output << "D;JGT" << endl;
|
||||
output << "@" << LABEL << "_FALSE" << endl;
|
||||
output << "D;JEQ" << endl;
|
||||
|
||||
output << "(" << LABEL << "_TRUE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=-1" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << "_FALSE)" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=0" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
output << "@" << LABEL << endl;
|
||||
output << "0;JMP" << endl;
|
||||
|
||||
output << "(" << LABEL << ")" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateAnd()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@AND" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@AND" << endl;
|
||||
output << "M=D&M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateOr()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@OR" << endl;
|
||||
output << "M=D" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@OR" << endl;
|
||||
output << "M=D|M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
string translateNot()
|
||||
{
|
||||
stringstream output;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "M=M-1" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "D=M" << endl;
|
||||
|
||||
output << "@SP" << endl;
|
||||
output << "A=M" << endl;
|
||||
output << "M=!D" << endl;
|
||||
output << "@SP" << endl;
|
||||
output << "M=M+1" << endl;
|
||||
|
||||
return output.str();
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Parser
|
||||
{
|
||||
private:
|
||||
ifstream file;
|
||||
string vmCode;
|
||||
|
||||
bool isEmptyLine(string text)
|
||||
{
|
||||
for (char c : text)
|
||||
{
|
||||
if (!isspace(c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeCommentsAndWhitespace()
|
||||
{
|
||||
string text;
|
||||
smatch matched;
|
||||
|
||||
while (getline(file, text))
|
||||
{
|
||||
if (regex_search(text, matched, regex("^(.*)?(\\/\\/.*)")) || isEmptyLine(text))
|
||||
{
|
||||
if (!isEmptyLine(matched[1]))
|
||||
{
|
||||
string command = matched[1];
|
||||
|
||||
trim(command);
|
||||
vmCode.append(command + '\n');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
trim(text);
|
||||
vmCode.append(text + '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void closeFile()
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
|
||||
public:
|
||||
Parser(string path)
|
||||
{
|
||||
file = ifstream(path);
|
||||
|
||||
removeCommentsAndWhitespace();
|
||||
}
|
||||
|
||||
vector<vector<string>> getCommands()
|
||||
{
|
||||
stringstream vmCodeStream(vmCode);
|
||||
string text;
|
||||
smatch matched;
|
||||
vector<vector<string>> commands;
|
||||
|
||||
while (getline(vmCodeStream, text, '\n'))
|
||||
{
|
||||
vector<string> matchedVector;
|
||||
|
||||
if (regex_search(text, matched, regex("^(.*) (.*) (.*)")))
|
||||
{
|
||||
matchedVector.push_back(matched[1]);
|
||||
matchedVector.push_back(matched[2]);
|
||||
matchedVector.push_back(matched[3]);
|
||||
}
|
||||
else if (regex_search(text, matched, regex("^(.*) (.*)")))
|
||||
{
|
||||
matchedVector.push_back(matched[1]);
|
||||
matchedVector.push_back(matched[2]);
|
||||
}
|
||||
else if (regex_search(text, matched, regex("^(.*)")))
|
||||
{
|
||||
matchedVector.push_back(matched[1]);
|
||||
}
|
||||
commands.push_back(matchedVector);
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
enum Segment
|
||||
{
|
||||
LCL,
|
||||
ARG,
|
||||
THIS,
|
||||
THAT,
|
||||
STATIC,
|
||||
CONSTANT,
|
||||
TEMP,
|
||||
POINTER,
|
||||
};
|
||||
|
||||
enum NoArgumentCommand {
|
||||
ADD,
|
||||
SUB,
|
||||
NEG,
|
||||
EQ,
|
||||
GT,
|
||||
LT,
|
||||
AND,
|
||||
OR,
|
||||
NOT,
|
||||
RETURN,
|
||||
};
|
||||
|
||||
enum OneArgumentCommand {
|
||||
LABEL,
|
||||
GOTO,
|
||||
IFGOTO,
|
||||
};
|
||||
|
||||
enum TwoArgumentCommand {
|
||||
PUSH,
|
||||
POP,
|
||||
FUNCTION,
|
||||
CALL
|
||||
};
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
inline void ltrim(string &str) {
|
||||
str.erase(str.begin(), find_if(str.begin(), str.end(), [](unsigned char ch) {
|
||||
return !isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
inline void rtrim(string &str) {
|
||||
str.erase(find_if(str.rbegin(), str.rend(), [](unsigned char ch) {
|
||||
return !isspace(ch);
|
||||
}).base(), str.end());
|
||||
}
|
||||
|
||||
inline void trim(string &str) {
|
||||
rtrim(str);
|
||||
ltrim(str);
|
||||
}
|
||||
|
||||
Segment determineSegment(string segment)
|
||||
{
|
||||
if (segment == "local")
|
||||
return Segment::LCL;
|
||||
if (segment == "argument")
|
||||
return Segment::ARG;
|
||||
if (segment == "this")
|
||||
return Segment::THIS;
|
||||
if (segment == "that")
|
||||
return Segment::THAT;
|
||||
if (segment == "pointer")
|
||||
return Segment::POINTER;
|
||||
if (segment == "static")
|
||||
return Segment::STATIC;
|
||||
if (segment == "temp")
|
||||
return Segment::TEMP;
|
||||
if (segment == "constant")
|
||||
return Segment::CONSTANT;
|
||||
|
||||
return Segment::CONSTANT;
|
||||
}
|
||||
|
||||
string generateRandomLabel(int length) {
|
||||
random_device rd;
|
||||
mt19937 gen(rd());
|
||||
uniform_int_distribution<> dis('A', 'Z');
|
||||
string label;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
label += static_cast<char>(dis(gen));
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
NoArgumentCommand determineNoArgumentCommand(string command)
|
||||
{
|
||||
if (command == "add")
|
||||
return NoArgumentCommand::ADD;
|
||||
if (command == "sub")
|
||||
return NoArgumentCommand::SUB;
|
||||
if (command == "neg")
|
||||
return NoArgumentCommand::NEG;
|
||||
if (command == "eq")
|
||||
return NoArgumentCommand::EQ;
|
||||
if (command == "gt")
|
||||
return NoArgumentCommand::GT;
|
||||
if (command == "lt")
|
||||
return NoArgumentCommand::LT;
|
||||
if (command == "and")
|
||||
return NoArgumentCommand::AND;
|
||||
if (command == "or")
|
||||
return NoArgumentCommand::OR;
|
||||
if (command == "not")
|
||||
return NoArgumentCommand::NOT;
|
||||
if (command == "return")
|
||||
return NoArgumentCommand::RETURN;
|
||||
|
||||
return NoArgumentCommand::NEG;
|
||||
}
|
||||
|
||||
OneArgumentCommand determineOneArgumentCommand(string command)
|
||||
{
|
||||
if (command == "label")
|
||||
return OneArgumentCommand::LABEL;
|
||||
if (command == "goto")
|
||||
return OneArgumentCommand::GOTO;
|
||||
if (command == "if-goto")
|
||||
return OneArgumentCommand::IFGOTO;
|
||||
|
||||
return OneArgumentCommand::IFGOTO;
|
||||
}
|
||||
|
||||
TwoArgumentCommand determineTwoArgumentCommand(string command)
|
||||
{
|
||||
if (command == "push")
|
||||
return TwoArgumentCommand::PUSH;
|
||||
if (command == "pop")
|
||||
return TwoArgumentCommand::POP;
|
||||
if (command == "function")
|
||||
return TwoArgumentCommand::FUNCTION;
|
||||
if (command == "call")
|
||||
return TwoArgumentCommand::CALL;
|
||||
|
||||
return TwoArgumentCommand::POP;
|
||||
}
|
||||
@@ -1,111 +1,3 @@
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
#include "include/parser.h"
|
||||
#include "include/code.h"
|
||||
|
||||
using namespace std;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
string constructTranslatedFilePath(string path)
|
||||
{
|
||||
size_t position = path.rfind(".vm");
|
||||
|
||||
return path.replace(position, 3, ".asm");
|
||||
}
|
||||
|
||||
string constructTranslatedDirectoryPath(string path)
|
||||
{
|
||||
string newPath = path;
|
||||
|
||||
size_t position = path.rfind("/");
|
||||
|
||||
if (position != string::npos && position == path.size() - 1)
|
||||
{
|
||||
newPath = path.replace(position, 1, "");
|
||||
}
|
||||
|
||||
size_t slashIndex = path.find_last_of('/');
|
||||
|
||||
newPath += "/" + path.substr(slashIndex + 1);
|
||||
|
||||
return newPath + ".asm";
|
||||
}
|
||||
|
||||
void processFile(string sourcePath)
|
||||
{
|
||||
Parser parser(sourcePath);
|
||||
|
||||
vector<vector<string>> commands = parser.getCommands();
|
||||
|
||||
string translatedPath = constructTranslatedFilePath(sourcePath);
|
||||
|
||||
Code code(translatedPath, commands, false);
|
||||
|
||||
code.translate();
|
||||
}
|
||||
|
||||
void processDirectory(string sourcePath, vector<string> files)
|
||||
{
|
||||
string translatedPath = constructTranslatedDirectoryPath(sourcePath);
|
||||
bool isNew = true;
|
||||
|
||||
for (const auto &file : files)
|
||||
{
|
||||
Parser parser(file);
|
||||
|
||||
vector<vector<string>> commands = parser.getCommands();
|
||||
|
||||
Code code(translatedPath, commands, isNew);
|
||||
|
||||
code.translate();
|
||||
|
||||
isNew = false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (!argv[1])
|
||||
{
|
||||
cout << "You must specify a vm file path!" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
string sourcePath = argv[1];
|
||||
|
||||
if (!regex_match(sourcePath, regex("^.+\\.vm")))
|
||||
{
|
||||
if (!fs::is_directory(sourcePath))
|
||||
{
|
||||
cerr << "Error: " << sourcePath << " is not a directory.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
vector<string> vmFiles;
|
||||
|
||||
for (const auto &entry : fs::directory_iterator(sourcePath))
|
||||
{
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".vm")
|
||||
{
|
||||
vmFiles.push_back(entry.path().string());
|
||||
}
|
||||
}
|
||||
|
||||
if (vmFiles.empty())
|
||||
{
|
||||
cout << "Directory does not contain vm files!" << sourcePath << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
processDirectory(sourcePath, vmFiles);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
processFile(sourcePath);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user