27 Commits

Author SHA1 Message Date
hazemKrimi 8225957c6a chore: update readme 2026-04-09 13:14:05 +01:00
hazemKrimi 641a4085b7 feat: handle function commands and bootstrap code 2026-04-08 00:07:44 +01:00
hazemKrimi fba936ea53 feat: handle branching commands 2026-04-07 16:05:28 +01:00
hazemKrimi 48b68c0247 chore: improve line cleanup from whitespace and comments 2026-04-07 16:05:05 +01:00
hazemKrimi 1ad35fcc26 chore: handle an argument consisting of a directory containing vm files 2026-04-07 14:49:08 +01:00
hazemKrimi 27ade5ab88 chore: rename the project back to vm translator 2026-04-06 16:21:13 +01:00
hazemKrimi 74982ac6e9 chore: move repetitive D register assignment commands into separate functions 2026-04-03 14:41:59 +01:00
hazemKrimi 9de4219cef chore: improve input and output paths handling 2026-04-02 12:57:50 +01:00
hazemKrimi e807d05f45 feat: translate stack, arithmetic, equality and bitwise operations 2026-04-01 17:03:04 +01:00
hazemKrimi 51c7327a65 chore: add segment names to parsed commands for easier translations 2026-04-01 17:02:36 +01:00
hazemKrimi a4e4942069 chore: include filename for static variables 2026-04-01 17:01:35 +01:00
hazemKrimi d01abac9e9 feat: code translation scaffolding 2026-03-30 15:59:50 +01:00
hazemKrimi 8888f7b97a chore: prevent duplicate definitions 2026-03-30 15:59:33 +01:00
hazemKrimi c8031fe6c7 feat: debug build 2026-03-27 16:53:45 +01:00
hazemKrimi 74beae32f3 fix: regex matching into enums in hashmap 2026-03-27 16:53:27 +01:00
hazemKrimi a43c055410 chore: use vector instead of custom linked list 2026-03-27 16:52:52 +01:00
hazemKrimi 90e5112afa chore: update sources in makefile 2026-03-26 13:24:04 +01:00
hazemKrimi a1d9a8a29c Merge pull request #1 from hazemKrimi/remake
feat: remake using procedural and generic programming paradigms in C++
2026-03-26 13:21:19 +01:00
hazemKrimi 5986a509e2 feat: parser initial scaffolding 2026-03-26 13:18:00 +01:00
hazemKrimi 595914175b feat: line checking utils 2026-03-26 13:17:44 +01:00
hazemKrimi 75615a8053 feat: vm translator types 2026-03-26 13:17:19 +01:00
hazemKrimi 33c2394142 chore: entrypoint initial scaffolding 2026-03-26 13:16:41 +01:00
hazemKrimi f94e7a7b8c chore: update gitignore 2026-03-26 13:16:10 +01:00
hazemKrimi e2b586e60c feat: makefile 2026-03-26 13:15:56 +01:00
hazemKrimi c892d1dd4e feat: generic linked list 2026-03-26 13:15:40 +01:00
hazemKrimi 087ad85dc7 chore: use double pointer notation 2026-03-24 10:55:54 +01:00
hazemKrimi fb9e783543 chore: scrap old implementation 2026-03-24 10:53:55 +01:00
20 changed files with 845 additions and 1191 deletions
+1 -3
View File
@@ -1,3 +1 @@
/.vscode out/
*.out
+29
View File
@@ -0,0 +1,29 @@
CC = g++
MODE ?= debug
ifeq ($(MODE), debug)
CFLAGS = -g -Wall -Wextra -DDEBUG
else
CFLAGS = -O2 -DNDEBUG -Wall -Wextra
endif
TARGET_NAME = vm-translator
OUT_DIR = out
TARGET = $(OUT_DIR)/$(TARGET_NAME)
SRCS = src/main.cpp src/utils.cpp src/code.cpp src/parser.cpp
OBJS = $(SRCS:src/%.cpp=$(OUT_DIR)/%.o)
$(TARGET): $(OBJS)
@mkdir -p $(OUT_DIR)
@$(CC) $(CFLAGS) $^ -o $@
@echo "Built $(TARGET_NAME): $@"
$(OUT_DIR)/%.o: src/%.cpp
@mkdir -p $(OUT_DIR)
@$(CC) $(CFLAGS) -c $< -o $@
clean:
@rm -rf out
@echo "Cleaned all builds."
.PHONY: all run clean
+37 -7
View File
@@ -1,13 +1,43 @@
# Jack Compiler # Jack VM Translator
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. This is a VM translator made as an assignment for the [Nand To Tetris Course: Part 2](https://nand2tetris.org/project07). It assumes that the VM files do not have errors for now.
## Requirements
You need a C++ compiler and `make` to develop, build, and run this project.
## Installation
1. Clone this repo:
To compile the program run the following command:
``` ```
g++ main.cpp -Isrc -std=c++17 git clone https://github.com/hazemKrimi/jack-vm-translator
``` ```
To run the executable against jack vm files run the following command with the path of the file:
2. To run this against VM files, run the following command with the path of the `.vm` file (or directory):
``` ```
./a.out <path> ./out/vm-translator <path_to_vm_file_or_directory>
``` ```
The file will be written next to the source file.
The result `.asm` file will be written in the same location as the source file.
## Build
- To build this project run the following command:
```
make
```
- To build for release run the following command:
```
make MODE=release
```
You will find the executable in the `out/` directory.
## Reference
This project is based on the [Nand To Tetrass Course: Part 2](https://www.nand2tetris.org/).
-39
View 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
View File
@@ -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;
}
}
}
}
};
-182
View File
@@ -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();
}
-139
View File
@@ -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();
}
-328
View File
@@ -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();
}
-99
View File
@@ -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;
}
};
-39
View File
@@ -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
View File
@@ -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;
}
-111
View File
@@ -1,111 +0,0 @@
#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);
}
return 0;
}
+462
View File
@@ -0,0 +1,462 @@
#include "types.hpp"
#include <iostream>
#include <sstream>
static int pushFromDRegisterToStack(std::ostringstream &stream) {
stream << "@SP" << std::endl;
stream << "A=M" << std::endl;
stream << "M=D" << std::endl;
stream << "@SP" << std::endl;
stream << "M=M+1" << std::endl;
return 0;
}
static int popFromStackToDRegister(std::ostringstream &stream) {
stream << "@SP" << std::endl;
stream << "M=M-1" << std::endl;
stream << "A=M" << std::endl;
stream << "D=M" << std::endl;
return 0;
}
static int translateStackOperation(std::ostringstream &stream,
const std::string fileName, Command cmd) {
switch (cmd.segmentType) {
case SegmentType::LCL:
case SegmentType::ARG:
case SegmentType::THIS:
case SegmentType::THAT:
stream << "@" << cmd.index << std::endl;
stream << "D=A" << std::endl;
stream << "@" << cmd.segmentName << std::endl;
if (cmd.commandType == CommandType::PUSH) {
stream << "A=D+M" << std::endl;
stream << "D=M" << std::endl;
} else {
stream << "D=D+M" << std::endl;
stream << "@ADDR" << std::endl;
stream << "M=D" << std::endl;
}
break;
case SegmentType::POINTER:
stream << (cmd.index == 0 ? "@THIS" : "@THAT") << std::endl;
if (cmd.commandType == CommandType::PUSH) {
stream << "D=M" << std::endl;
} else {
stream << "D=A" << std::endl;
stream << "@ADDR" << std::endl;
stream << "M=D" << std::endl;
}
break;
case SegmentType::STATIC:
stream << "@" << fileName << "." << cmd.index << std::endl;
if (cmd.commandType == CommandType::PUSH) {
stream << "D=M" << std::endl;
} else {
stream << "D=A" << std::endl;
stream << "@ADDR" << std::endl;
stream << "M=D" << std::endl;
}
break;
case SegmentType::TEMP:
stream << "@" << cmd.index + 5 << std::endl;
if (cmd.commandType == CommandType::PUSH) {
stream << "D=M" << std::endl;
} else {
stream << "D=A" << std::endl;
stream << "@ADDR" << std::endl;
stream << "M=D" << std::endl;
}
break;
case SegmentType::CONSTANT:
if (cmd.commandType == CommandType::POP)
return 1;
stream << "@" << cmd.index << std::endl;
stream << "D=A" << std::endl;
break;
default:
break;
}
stream << "@SP" << std::endl;
if (cmd.commandType == CommandType::PUSH) {
stream << "A=M" << std::endl;
stream << "M=D" << std::endl;
stream << "@SP" << std::endl;
stream << "M=M+1" << std::endl;
} else {
stream << "M=M-1" << std::endl;
stream << "A=M" << std::endl;
stream << "D=M" << std::endl;
stream << "@ADDR" << std::endl;
stream << "A=M" << std::endl;
stream << "M=D" << std::endl;
}
return 0;
}
static int translateArithmeticBinaryOperation(std::ostringstream &stream,
Command cmd) {
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@BINARY_ARITHMETIC" << std::endl;
stream << "M=D" << std::endl;
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@BINARY_ARITHMETIC" << std::endl;
if (cmd.commandType == CommandType::ADD) {
stream << "M=D+M" << std::endl;
} else {
stream << "M=D-M" << std::endl;
}
stream << "D=M" << std::endl;
return pushFromDRegisterToStack(stream);
}
static int translateArithmeticUnaryOperation(std::ostringstream &stream) {
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@NEGATE" << std::endl;
stream << "M=D" << std::endl;
stream << "M=M-D" << std::endl;
stream << "M=M-D" << std::endl;
stream << "D=M" << std::endl;
return pushFromDRegisterToStack(stream);
}
static int translateEqualityOperation(std::ostringstream &stream, Command cmd) {
static int equalityCheckLabelCounter = 0;
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@EQUALITY_CHECK" << std::endl;
stream << "M=D" << std::endl;
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@EQUALITY_CHECK" << std::endl;
stream << "M=D-M" << std::endl;
stream << "D=M" << std::endl;
stream << "@" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << "_TRUE"
<< std::endl;
stream << "D;"
<< (cmd.commandType == CommandType::GT ? "JGT"
: cmd.commandType == CommandType::LT ? "JLT"
: "JEQ")
<< std::endl;
stream << "@" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << "_FALSE"
<< std::endl;
stream << "0;JMP" << std::endl;
stream << "(" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << "_TRUE)"
<< std::endl;
stream << "@SP" << std::endl;
stream << "A=M" << std::endl;
stream << "M=-1" << std::endl;
stream << "@SP" << std::endl;
stream << "M=M+1" << std::endl;
stream << "@" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << std::endl;
stream << "0;JMP" << std::endl;
stream << "(" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << "_FALSE)"
<< std::endl;
stream << "@SP" << std::endl;
stream << "A=M" << std::endl;
stream << "M=0" << std::endl;
stream << "@SP" << std::endl;
stream << "M=M+1" << std::endl;
stream << "@" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << std::endl;
stream << "0;JMP" << std::endl;
stream << "(" << "EQUALITY_CHECK_" << equalityCheckLabelCounter << ")"
<< std::endl;
equalityCheckLabelCounter++;
return 0;
}
static int translateBitwiseBinaryOperation(std::ostringstream &stream,
Command cmd) {
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@BINARY_BITWISE" << std::endl;
stream << "M=D" << std::endl;
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@BINARY_BITWISE" << std::endl;
if (cmd.commandType == CommandType::AND) {
stream << "M=D&M" << std::endl;
} else {
stream << "M=D|M" << std::endl;
}
stream << "D=M" << std::endl;
return pushFromDRegisterToStack(stream);
}
static int translateBistwiseUnaryOperation(std::ostringstream &stream) {
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@SP" << std::endl;
stream << "A=M" << std::endl;
stream << "M=!D" << std::endl;
stream << "@SP" << std::endl;
stream << "M=M+1" << std::endl;
return 0;
}
static int translateLabel(std::ostringstream &stream, Command cmd) {
stream << "(" << cmd.label << ")" << std::endl;
return 0;
}
static int translateGoTo(std::ostringstream &stream, Command cmd) {
stream << "@" << cmd.label << std::endl;
stream << "0;JMP" << std::endl;
return 0;
}
static int translateIfGoTo(std::ostringstream &stream, Command cmd) {
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@" << cmd.label << std::endl;
stream << "D;JNE" << std::endl;
return 0;
}
static int translateFunctionDefinition(std::ostringstream &stream,
Command cmd) {
stream << "(" << cmd.label << ")" << std::endl;
for (int i = 0; i < cmd.index; ++i) {
stream << "@0" << std::endl;
stream << "D=A" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
}
return 0;
}
int translateFunctionCall(std::ostringstream &stream, Command cmd) {
static int callCounter = 0;
std::string returnLabel = cmd.label + "$ret" + std::to_string(callCounter++);
stream << "@" << returnLabel << std::endl;
stream << "D=A" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
stream << "@LCL" << std::endl;
stream << "D=M" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
stream << "@ARG" << std::endl;
stream << "D=M" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
stream << "@THIS" << std::endl;
stream << "D=M" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
stream << "@THAT" << std::endl;
stream << "D=M" << std::endl;
if (pushFromDRegisterToStack(stream) != 0)
return 1;
stream << "@SP" << std::endl;
stream << "D=M" << std::endl;
stream << "@5" << std::endl;
stream << "D=D-A" << std::endl;
stream << "@" << cmd.index << std::endl;
stream << "D=D-A" << std::endl;
stream << "@ARG" << std::endl;
stream << "M=D" << std::endl;
stream << "@SP" << std::endl;
stream << "D=M" << std::endl;
stream << "@LCL" << std::endl;
stream << "M=D" << std::endl;
stream << "@" << cmd.label << std::endl;
stream << "0;JMP" << std::endl;
stream << "(" << returnLabel << ")" << std::endl;
return 0;
}
static int translateFunctionReturn(std::ostringstream &stream) {
stream << "@LCL" << std::endl;
stream << "D=M" << std::endl;
stream << "@FRAME" << std::endl;
stream << "M=D" << std::endl;
stream << "@5" << std::endl;
stream << "D=A" << std::endl;
stream << "@FRAME" << std::endl;
stream << "D=M-D" << std::endl;
stream << "A=D" << std::endl;
stream << "D=M" << std::endl;
stream << "@RETURN_ADDRESS" << std::endl;
stream << "M=D" << std::endl;
stream << "@ARG" << std::endl;
stream << "D=M" << std::endl;
stream << "@ADDR" << std::endl;
stream << "M=D" << std::endl;
if (popFromStackToDRegister(stream) != 0)
return 1;
stream << "@ADDR" << std::endl;
stream << "A=M" << std::endl;
stream << "M=D" << std::endl;
stream << "@ARG" << std::endl;
stream << "D=M+1" << std::endl;
stream << "@SP" << std::endl;
stream << "M=D" << std::endl;
stream << "@FRAME" << std::endl;
stream << "D=M" << std::endl;
stream << "@1" << std::endl;
stream << "D=D-A" << std::endl;
stream << "A=D" << std::endl;
stream << "D=M" << std::endl;
stream << "@THAT" << std::endl;
stream << "M=D" << std::endl;
stream << "@FRAME" << std::endl;
stream << "D=M" << std::endl;
stream << "@2" << std::endl;
stream << "D=D-A" << std::endl;
stream << "A=D" << std::endl;
stream << "D=M" << std::endl;
stream << "@THIS" << std::endl;
stream << "M=D" << std::endl;
stream << "@FRAME" << std::endl;
stream << "D=M" << std::endl;
stream << "@3" << std::endl;
stream << "D=D-A" << std::endl;
stream << "A=D" << std::endl;
stream << "D=M" << std::endl;
stream << "@ARG" << std::endl;
stream << "M=D" << std::endl;
stream << "@FRAME" << std::endl;
stream << "D=M" << std::endl;
stream << "@4" << std::endl;
stream << "D=D-A" << std::endl;
stream << "A=D" << std::endl;
stream << "D=M" << std::endl;
stream << "@LCL" << std::endl;
stream << "M=D" << std::endl;
stream << "@RETURN_ADDRESS" << std::endl;
stream << "A=M" << std::endl;
stream << "M;JMP" << std::endl;
return 0;
}
int translateCommand(std::string &output, const std::string fileName,
Command cmd) {
std::ostringstream stream;
stream << "// " << cmd.line << std::endl;
stream << std::endl;
switch (cmd.commandType) {
case CommandType::PUSH:
case CommandType::POP:
translateStackOperation(stream, fileName, cmd);
break;
case CommandType::ADD:
case CommandType::SUB:
translateArithmeticBinaryOperation(stream, cmd);
break;
case CommandType::NEG:
translateArithmeticUnaryOperation(stream);
break;
case CommandType::EQ:
case CommandType::GT:
case CommandType::LT:
translateEqualityOperation(stream, cmd);
break;
case CommandType::AND:
case CommandType::OR:
translateBitwiseBinaryOperation(stream, cmd);
break;
case CommandType::NOT:
translateBistwiseUnaryOperation(stream);
break;
case CommandType::LABEL:
translateLabel(stream, cmd);
break;
case CommandType::GOTO:
translateGoTo(stream, cmd);
break;
case CommandType::IFGOTO:
translateIfGoTo(stream, cmd);
break;
case CommandType::FUNCTION:
translateFunctionDefinition(stream, cmd);
break;
case CommandType::CALL:
translateFunctionCall(stream, cmd);
break;
case CommandType::RETURN:
translateFunctionReturn(stream);
break;
default:
break;
}
stream << std::endl;
output = stream.str();
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
#include "types.hpp"
int translateFunctionCall(std::ostringstream&, Command);
int translateCommand(std::string&, const std::string, Command);
+114
View File
@@ -0,0 +1,114 @@
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
#include "code.hpp"
#include "parser.hpp"
#include "utils.hpp"
int process(std::string inputPath, std::string outputPath,
std::ios_base::openmode outputStreamMode, bool &init) {
std::ifstream ifs(inputPath);
std::ofstream ofs(outputPath, outputStreamMode);
std::string fileName = getFileNameFromFilePath(inputPath);
std::string line;
std::string output;
if (init) {
std::ostringstream initStream;
Command cmd;
initStream << "// " << "SP = 256" << std::endl;
initStream << std::endl;
initStream << "@256" << std::endl;
initStream << "D=A" << std::endl;
initStream << "@SP" << std::endl;
initStream << "M=D" << std::endl;
cmd.label = "Sys.init";
cmd.commandType = CommandType::CALL;
cmd.index = 0;
initStream << std::endl;
initStream << "// " << "call Sys.init 0" << std::endl;
initStream << std::endl;
if (translateFunctionCall(initStream, cmd) != 0)
exit(1);
initStream << std::endl;
output = initStream.str();
ofs << output;
init = false;
}
std::vector<Command> commands;
while (getline(ifs, line)) {
if (cleanupLine(line) != 0)
exit(1);
if (isEmptyLine(line))
continue;
if (parseCommand(commands, line) != 0)
exit(1);
}
for (const Command &cmd : commands) {
if (translateCommand(output, fileName, cmd) != 0)
exit(1);
ofs << output;
}
ifs.close();
ofs.close();
return 0;
}
int main(int argc, char **argv) {
if (argc != 2) {
std::cerr << "You must specify an argument for the vm file to translate!"
<< std::endl;
exit(1);
}
bool init = false;
if (regex_match(argv[1], std::regex("^.+\\.vm")))
return process(argv[1], getOutputPath(argv[1]), std::ofstream::trunc, init);
if (!std::filesystem::is_directory(argv[1])) {
std::cerr << "Argument is not a VM file!" << std::endl;
exit(1);
}
std::string outputPath = getOutputPath(argv[1]);
if (std::filesystem::exists(outputPath)) {
std::filesystem::remove(outputPath);
}
for (const auto &entry : std::filesystem::directory_iterator(argv[1])) {
if (entry.is_regular_file() && entry.path().filename() == "Sys.vm") {
init = true;
}
}
for (const auto &entry : std::filesystem::directory_iterator(argv[1])) {
if (entry.is_regular_file() && entry.path().extension() == ".vm") {
if (process(entry.path().string(), outputPath, std::ofstream::app,
init) != 0)
exit(1);
}
}
}
+60
View File
@@ -0,0 +1,60 @@
#include <iostream>
#include <regex>
#include <string>
#include <vector>
#include "parser.hpp"
int parseCommand(std::vector<Command> &commands, std::string line) {
std::smatch matched;
if (regex_search(line, matched, std::regex("^(\\S+)\\s+(\\S+)\\s+(\\S+)$"))) {
Command cmd;
if (matched.ready()) {
std::string segment = matched[2];
cmd.line = line;
cmd.commandType = commandTypes.at(matched[1]);
cmd.index = std::stoi(std::string(matched[3]));
if (cmd.commandType == CommandType::FUNCTION ||
cmd.commandType == CommandType::CALL) {
cmd.label = matched[2];
} else {
cmd.segmentType = segmentTypes.at(segment);
cmd.segmentName = segmentNames.at(segment);
}
}
commands.push_back(cmd);
return 0;
}
if (std::regex_search(line, matched, std::regex("^(\\S+)\\s+(\\S+)$"))) {
Command cmd;
if (matched.ready()) {
cmd.line = line;
cmd.commandType = commandTypes.at(matched[1]);
cmd.label = matched[2];
}
commands.push_back(cmd);
return 0;
}
if (regex_search(line, matched, std::regex("^(\\S+)$"))) {
Command cmd;
if (matched.ready()) {
cmd.line = line;
cmd.commandType = commandTypes.at(matched[1]);
}
commands.push_back(cmd);
return 0;
}
std::cerr << "Incorrect vm command: " << line << std::endl;
return 1;
}
+6
View File
@@ -0,0 +1,6 @@
#include <string>
#include <vector>
#include "types.hpp"
int parseCommand(std::vector<Command>&, std::string);
+79
View File
@@ -0,0 +1,79 @@
#include <string>
#include <unordered_map>
#ifndef TYPES
enum class CommandType {
ADD,
SUB,
NEG,
EQ,
GT,
LT,
AND,
OR,
NOT,
PUSH,
POP,
LABEL,
GOTO,
IFGOTO,
FUNCTION,
CALL,
RETURN
};
enum class SegmentType {
LCL,
ARG,
THIS,
THAT,
STATIC,
CONSTANT,
TEMP,
POINTER,
};
std::unordered_map<std::string, CommandType> const commandTypes = {
{"add", CommandType::ADD},
{"sub", CommandType::SUB},
{"neg", CommandType::NEG},
{"eq", CommandType::EQ},
{"gt", CommandType::GT},
{"lt", CommandType::LT},
{"and", CommandType::AND},
{"or", CommandType::OR},
{"not", CommandType::NOT},
{"push", CommandType::PUSH},
{"pop", CommandType::POP},
{"label", CommandType::LABEL},
{"goto", CommandType::GOTO},
{"if-goto", CommandType::IFGOTO},
{"function", CommandType::FUNCTION},
{"call", CommandType::CALL},
{"return", CommandType::RETURN}};
std::unordered_map<std::string, SegmentType> const segmentTypes = {
{"local", SegmentType::LCL}, {"argument", SegmentType::ARG},
{"this", SegmentType::THIS}, {"that", SegmentType::THAT},
{"static", SegmentType::STATIC}, {"constant", SegmentType::CONSTANT},
{"temp", SegmentType::TEMP}, {"pointer", SegmentType::POINTER},
};
std::unordered_map<std::string, std::string> const segmentNames = {
{"local", "LCL"}, {"argument", "ARG"}, {"this", "THIS"},
{"that", "THAT"}, {"static", "NONE"}, {"constant", "NONE"},
{"temp", "NONE"}, {"pointer", "NONE"},
};
typedef struct {
std::string line;
CommandType commandType;
SegmentType segmentType;
std::string segmentName;
std::string label;
int index;
} Command;
#define TYPES
#endif
+47
View File
@@ -0,0 +1,47 @@
#include <filesystem>
#include <string>
bool isEmptyLine(const std::string &line) {
for (char c : line) {
if (!isspace(c))
return false;
}
return true;
}
int cleanupLine(std::string &line) {
size_t commentStartingPosition = line.find("//");
if (commentStartingPosition != std::string::npos) {
line = line.substr(0, commentStartingPosition);
}
size_t firstNonWhiteSpacePosition = line.find_first_not_of(" \t\n\r");
if (firstNonWhiteSpacePosition == std::string::npos) {
line = "";
return 0;
}
size_t lastNonWhiteSpacePosition = line.find_last_not_of(" \t\n\r");
line =
line.substr(firstNonWhiteSpacePosition,
(lastNonWhiteSpacePosition - firstNonWhiteSpacePosition + 1));
return 0;
}
std::string getFileNameFromFilePath(const std::string &path) {
std::string fileName = path.substr(path.find_last_of("/\\") + 1);
return fileName.substr(0, fileName.find_last_of('.'));
}
std::string getOutputPath(const std::string &path) {
if (std::filesystem::is_directory(path)) {
return path + "/" + path.substr(path.find_last_of("/\\") + 1) + ".asm";
}
return path.substr(0, path.find_last_of('.')) + ".asm";
}
+6
View File
@@ -0,0 +1,6 @@
#include <string>
bool isEmptyLine(const std::string&);
int cleanupLine(std::string&);
std::string getFileNameFromFilePath(const std::string&);
std::string getOutputPath(const std::string&);