21 Commits
v1.0 ... master

Author SHA1 Message Date
avinal
57dfa048cf cleaned code 2020-08-22 23:52:20 +05:30
avinal
df2c013ab3 cleaned test files 2020-08-22 23:36:54 +05:30
avinal
07a7f480a8 example files 2020-08-21 19:39:55 +05:30
avinal
56b35b12ca readme updated 2020-08-21 19:39:38 +05:30
avinal
a11558120b gitignore updated 2020-08-21 19:39:23 +05:30
avinal
291b239065 headers updated 2020-08-21 19:08:23 +05:30
avinal
4332eae357 minor update 2020-08-21 19:08:04 +05:30
avinal
68748fed47 makefile updated 2020-08-21 19:07:43 +05:30
avinal
25304b4662 source files added 2020-08-21 18:52:02 +05:30
avinal
4ef8187412 redundant files removed 2020-08-21 18:51:41 +05:30
avinal
b4b19da495 headers added 2020-08-21 18:51:18 +05:30
avinal
30921da66c folder reorganised 2020-08-21 18:50:50 +05:30
avinal
d3e3f8f701 folder reorganisation 2020-08-21 18:50:08 +05:30
avinal
5a864e1a78 example files added 2020-08-21 18:49:30 +05:30
avinal
4f577ea7c6 trim command updated 2020-08-21 17:56:06 +05:30
avinal
5444102bef experimental flag added 2020-08-21 17:55:35 +05:30
avinal
7d85cebda1 added filesystem 2020-08-21 17:55:16 +05:30
avinal
236fe8e556 modified for part 2 2020-08-21 17:55:01 +05:30
avinal
274bbde1c4 added newer definations for part 2 2020-08-21 17:54:38 +05:30
avinal
c59bd2122c made slight changes 2020-08-21 17:54:14 +05:30
avinal
1a8a9d38ac gitignore updated 2020-08-21 12:48:43 +05:30
40 changed files with 1230 additions and 454 deletions

1
.gitignore vendored
View File

@@ -35,4 +35,3 @@ VMTranslator
*.asm
.vscode
*.zip

View File

@@ -1,9 +0,0 @@
#include "code_writer.hpp"
#include <iostream>
int main(int argc, char const *argv[])
{
code_writer toassembly(argv[1]);
toassembly.write_assembly();
return 0;
}

View File

@@ -1,29 +1,25 @@
CXX = g++
STDVERSION = -std=c++17
STDVERSION = -std=c++17 -lstdc++fs
WARNINGS = -pedantic -Wall -Wfatal-errors -Wextra -Wno-unused-parameter -Wno-unused-variable
TARGET = VMTranslator
OBJ_DIR = build
OBJECTS = code_writer.o parser.o vutility.o
TEST_OBJS = parser_test.o
all:$(TARGET)
$(TARGET): $(OBJECTS)
$(CXX) $(WARNINGS) $(STDVERSION) -o $(TARGET) Main.cpp $(OBJECTS)
$(CXX) $(WARNINGS) -o $(TARGET) src/Main.cpp $(OBJECTS) $(STDVERSION)
vutility.o: vutility.cpp vutility.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c vutility.cpp -o vutility.o
vutility.o: src/vutility.cpp include/vutility.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/vutility.cpp -o vutility.o
parser.o: parser.cpp parser.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c parser.cpp -o parser.o
parser.o: src/parser.cpp include/parser.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/parser.cpp -o parser.o
code_writer.o:code_writer.cpp code_writer.hpp
$(CXX) $(STDVERSION) -c code_writer.cpp -o code_writer.o
code_writer.o: src/code_writer.cpp include/code_writer.hpp
$(CXX) $(WARNINGS) $(STDVERSION) -c src/code_writer.cpp -o code_writer.o
test:
$(CXX) $(STDVERSION) tests/*.cpp tests/catch/catch_main.cpp parser.cpp code_writer.cpp -o test
clean:
rm -rf *.o $(TARGET) *.asm

View File

@@ -1,2 +1,65 @@
# The-VM-to-HACK-Translator
Translates Virtual Machine Language into HACK Assembly language.
**Important: If you are taking this course then I suggest you to try to write the assembler yourself first, it is not very easy and not very tough too. At least not impossible, because I did it 😘**
## Get Started with the project
1. Directory Structure
```shell
.
|_include # Contains headers
|_src # Contains Source Code and Main
|_Test-Files # Example HACK VM Files
```
2. Clone this repo
```shell
git clone https://github.com/avinal/The-VM-to-HACK-Translator.git
```
3. Build and run, provide only [HACK VM Language](https://www.nand2tetris.org/project08) file. Don't confuse with `.vm` extesion.
```shell
cd The-VM-to-HACK-Translator
make
./VMTranslator file.vm
```
4. Start over after modification
```shell
make clean
```
## Tips
In case you want to modify this project, you can use [Boost C++ Libraries](https://www.boost.org/), they can simplify many tasks needed by this project.
## Some Words
This was a nice project and taugh me many things. Given below are some miraculous code snippets that proved to be really useful and are well researched. Hope you will find them useful.
1. Trim spaces, comments, carrige returns, newline, tab and verticle tabs:
```cpp
inline std::string trim(std::string str)
{
if (str.find('/') != std::string::npos) // comments
{
str.erase(str.find('/'));
}
str.erase(0, str.find_first_not_of(" \r\t\v\n")); //prefixing
str.erase(str.find_last_not_of(" \r\t\v\n") + 1); //surfixing}
return str;
}
```
2. Tokenize a string using C++ with respect to a delimiter, space by defalt (string split):
```cpp
#include <sstream>
#include <vector>
std::vector<std::string> split(std::string str, char delimiter = ' ')
{
std::vector<std::string> tokens;
std::stringstream tokenizer(str);
std::string intermediate;
while (std::getline(tokenizer, intermediate, delimiter))
{
tokens.push_back(intermediate);
}
return tokens;
}
```
3. **Fascinating** Using Lambdas with Map to implement a function or function pointers. [See here](https://github.com/avinal/The-VM-to-HACK-Translator/blob/291b239065fc5cc0921b8592dfcd69c6f3022e52/src/code_writer.cpp#L29)

22
Test-Files/BasicLoop.vm Normal file
View File

@@ -0,0 +1,22 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/ProgramFlow/BasicLoop/BasicLoop.vm
// Computes the sum 1 + 2 + ... + argument[0] and pushes the
// result onto the stack. Argument[0] is initialized by the test
// script before this code starts running.
push constant 0
pop local 0 // initializes sum = 0
label LOOP_START
push argument 0
push local 0
add
pop local 0 // sum = sum + counter
push argument 0
push constant 1
sub
pop argument 0 // counter--
push argument 0
if-goto LOOP_START // If counter > 0, goto LOOP_START
push local 0

View File

@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|
| 262 | 3 |

View File

@@ -0,0 +1,18 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/FibonacciElement/FibonacciElement.tst
// FibonacciElement.asm results from translating both Main.vm and Sys.vm into
// a single assembly program, stored in the file FibonacciElement.asm.
load FibonacciElement.asm,
output-file FibonacciElement.out,
compare-to FibonacciElement.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
repeat 6000 {
ticktock;
}
output;

View File

@@ -0,0 +1,17 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/FibonacciElement/FibonacciElementVME.tst
load, // Load all the VM files from the current directory
output-file FibonacciElement.out,
compare-to FibonacciElement.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1;
set sp 261,
repeat 110 {
vmstep;
}
output;

View File

@@ -0,0 +1,30 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/FibonacciElement/Main.vm
// Computes the n'th element of the Fibonacci series, recursively.
// n is given in argument[0]. Called by the Sys.init function
// (part of the Sys.vm file), which also pushes the argument[0]
// parameter before this code starts running.
function Main.fibonacci 0
push argument 0
push constant 2
lt // checks if n<2
if-goto IF_TRUE
goto IF_FALSE
label IF_TRUE // if n<2, return n
push argument 0
return
label IF_FALSE // if n>=2, returns fib(n-2)+fib(n-1)
push argument 0
push constant 2
sub
call Main.fibonacci 1 // computes fib(n-2)
push argument 0
push constant 1
sub
call Main.fibonacci 1 // computes fib(n-1)
add // returns fib(n-1) + fib(n-2)
return

View File

@@ -0,0 +1,16 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/FibonacciElement/Sys.vm
// Pushes a constant, say n, onto the stack, and calls the Main.fibonacii
// function, which computes the n'th element of the Fibonacci series.
// Note that by convention, the Sys.init function is called "automatically"
// by the bootstrap code.
function Sys.init 0
push constant 4
call Main.fibonacci 1 // computes the 4'th fibonacci element
label WHILE
goto WHILE // loops infinitely

View File

@@ -0,0 +1,49 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/ProgramFlow/FibonacciSeries/FibonacciSeries.vm
// Puts the first argument[0] elements of the Fibonacci series
// in the memory, starting in the address given in argument[1].
// Argument[0] and argument[1] are initialized by the test script
// before this code starts running.
push argument 1
pop pointer 1 // that = argument[1]
push constant 0
pop that 0 // first element in the series = 0
push constant 1
pop that 1 // second element in the series = 1
push argument 0
push constant 2
sub
pop argument 0 // num_of_elements -= 2 (first 2 elements are set)
label MAIN_LOOP_START
push argument 0
if-goto COMPUTE_ELEMENT // if num_of_elements > 0, goto COMPUTE_ELEMENT
goto END_PROGRAM // otherwise, goto END_PROGRAM
label COMPUTE_ELEMENT
push that 0
push that 1
add
pop that 2 // that[2] = that[0] + that[1]
push pointer 1
push constant 1
add
pop pointer 1 // that += 1
push argument 0
push constant 1
sub
pop argument 0 // num_of_elements--
goto MAIN_LOOP_START
label END_PROGRAM

View File

@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] | RAM[5] | RAM[6] |
| 261 | 261 | 256 | 4000 | 5000 | 135 | 246 |

View File

@@ -0,0 +1,65 @@
// Test file for NestedCall test.
load NestedCall.asm,
output-file NestedCall.out,
compare-to NestedCall.cmp,
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
set RAM[0] 261,
set RAM[1] 261,
set RAM[2] 256,
set RAM[3] -3,
set RAM[4] -4,
set RAM[5] -1, // test results
set RAM[6] -1,
set RAM[256] 1234, // fake stack frame from call Sys.init
set RAM[257] -1,
set RAM[258] -2,
set RAM[259] -3,
set RAM[260] -4,
set RAM[261] -1, // Initialize stack to check for local segment
set RAM[262] -1, // being cleared to zero.
set RAM[263] -1,
set RAM[264] -1,
set RAM[265] -1,
set RAM[266] -1,
set RAM[267] -1,
set RAM[268] -1,
set RAM[269] -1,
set RAM[270] -1,
set RAM[271] -1,
set RAM[272] -1,
set RAM[273] -1,
set RAM[274] -1,
set RAM[275] -1,
set RAM[276] -1,
set RAM[277] -1,
set RAM[278] -1,
set RAM[279] -1,
set RAM[280] -1,
set RAM[281] -1,
set RAM[282] -1,
set RAM[283] -1,
set RAM[284] -1,
set RAM[285] -1,
set RAM[286] -1,
set RAM[287] -1,
set RAM[288] -1,
set RAM[289] -1,
set RAM[290] -1,
set RAM[291] -1,
set RAM[292] -1,
set RAM[293] -1,
set RAM[294] -1,
set RAM[295] -1,
set RAM[296] -1,
set RAM[297] -1,
set RAM[298] -1,
set RAM[299] -1,
repeat 4000 {
ticktock;
}
output;

View File

@@ -0,0 +1,70 @@
// Test file for NestedCall test.
load Sys.vm,
output-file NestedCall.out,
compare-to NestedCall.cmp,
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1 RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[5]%D1.6.1 RAM[6]%D1.6.1;
set RAM[0] 261,
set RAM[1] 261,
set RAM[2] 256,
set RAM[3] -3,
set RAM[4] -4,
set RAM[5] -1, // test results
set RAM[6] -1,
set RAM[256] 1234, // fake stack frame from call Sys.init
set RAM[257] -1,
set RAM[258] -2,
set RAM[259] -3,
set RAM[260] -4,
set RAM[261] -1, // Initialize stack to check for local segment
set RAM[262] -1, // being cleared to zero.
set RAM[263] -1,
set RAM[264] -1,
set RAM[265] -1,
set RAM[266] -1,
set RAM[267] -1,
set RAM[268] -1,
set RAM[269] -1,
set RAM[270] -1,
set RAM[271] -1,
set RAM[272] -1,
set RAM[273] -1,
set RAM[274] -1,
set RAM[275] -1,
set RAM[276] -1,
set RAM[277] -1,
set RAM[278] -1,
set RAM[279] -1,
set RAM[280] -1,
set RAM[281] -1,
set RAM[282] -1,
set RAM[283] -1,
set RAM[284] -1,
set RAM[285] -1,
set RAM[286] -1,
set RAM[287] -1,
set RAM[288] -1,
set RAM[289] -1,
set RAM[290] -1,
set RAM[291] -1,
set RAM[292] -1,
set RAM[293] -1,
set RAM[294] -1,
set RAM[295] -1,
set RAM[296] -1,
set RAM[297] -1,
set RAM[298] -1,
set RAM[299] -1,
set sp 261,
set local 261,
set argument 256,
set this 3000,
set that 4000;
repeat 50 {
vmstep;
}
output;

View File

@@ -0,0 +1,63 @@
// Sys.vm for NestedCall test.
// Sys.init()
//
// Calls Sys.main() and stores return value in temp 1.
// Does not return. (Enters infinite loop.)
function Sys.init 0
push constant 4000 // test THIS and THAT context save
pop pointer 0
push constant 5000
pop pointer 1
call Sys.main 0
pop temp 1
label LOOP
goto LOOP
// Sys.main()
//
// Sets locals 1, 2 and 3, leaving locals 0 and 4 unchanged to test
// default local initialization to 0. (RAM set to -1 by test setup.)
// Calls Sys.add12(123) and stores return value (135) in temp 0.
// Returns local 0 + local 1 + local 2 + local 3 + local 4 (456) to confirm
// that locals were not mangled by function call.
function Sys.main 5
push constant 4001
pop pointer 0
push constant 5001
pop pointer 1
push constant 200
pop local 1
push constant 40
pop local 2
push constant 6
pop local 3
push constant 123
call Sys.add12 1
pop temp 0
push local 0
push local 1
push local 2
push local 3
push local 4
add
add
add
add
return
// Sys.add12(int n)
//
// Returns n+12.
function Sys.add12 0
push constant 4002
pop pointer 0
push constant 5002
pop pointer 1
push argument 0
push constant 12
add
return

View File

@@ -0,0 +1,2 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|
| 311 | 305 | 300 | 3010 | 4010 | 1196 |

View File

@@ -0,0 +1,29 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunction.tst
load SimpleFunction.asm,
output-file SimpleFunction.out,
compare-to SimpleFunction.cmp,
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
set RAM[0] 317,
set RAM[1] 317,
set RAM[2] 310,
set RAM[3] 3000,
set RAM[4] 4000,
set RAM[310] 1234,
set RAM[311] 37,
set RAM[312] 1000,
set RAM[313] 305,
set RAM[314] 300,
set RAM[315] 3010,
set RAM[316] 4010,
repeat 300 {
ticktock;
}
output;

View File

@@ -0,0 +1,16 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunction.vm
// Performs a simple calculation and returns the result.
function SimpleFunction.test 2
push local 0
push local 1
add
not
push argument 0
add
push argument 1
sub
return

View File

@@ -0,0 +1,29 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/SimpleFunction/SimpleFunctionVME.tst
load SimpleFunction.vm,
output-file SimpleFunction.out,
compare-to SimpleFunction.cmp,
output-list RAM[0]%D1.6.1 RAM[1]%D1.6.1 RAM[2]%D1.6.1
RAM[3]%D1.6.1 RAM[4]%D1.6.1 RAM[310]%D1.6.1;
set sp 317,
set local 317,
set argument 310,
set this 3000,
set that 4000,
set argument[0] 1234,
set argument[1] 37,
set argument[2] 9,
set argument[3] 305,
set argument[4] 300,
set argument[5] 3010,
set argument[6] 4010,
repeat 10 {
vmstep;
}
output;

View File

@@ -0,0 +1,20 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/StaticsTest/Class1.vm
// Stores two supplied arguments in static[0] and static[1].
function Class1.set 0
push argument 0
pop static 0
push argument 1
pop static 1
push constant 0
return
// Returns static[0] - static[1].
function Class1.get 0
push static 0
push static 1
sub
return

View File

@@ -0,0 +1,20 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/StaticsTest/Class2.vm
// Stores two supplied arguments in static[0] and static[1].
function Class2.set 0
push argument 0
pop static 0
push argument 1
pop static 1
push constant 0
return
// Returns static[0] - static[1].
function Class2.get 0
push static 0
push static 1
sub
return

View File

@@ -0,0 +1,2 @@
| RAM[0] |RAM[261]|RAM[262]|
| 263 | -2 | 8 |

View File

@@ -0,0 +1,17 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/StaticsTest/StaticsTest.tst
load StaticsTest.asm,
output-file StaticsTest.out,
compare-to StaticsTest.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
set RAM[0] 256,
repeat 2500 {
ticktock;
}
output;

View File

@@ -0,0 +1,17 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/StaticsTest/StaticsTestVME.tst
load, // loads all the VM files from the current directory.
output-file StaticsTest.out,
compare-to StaticsTest.cmp,
output-list RAM[0]%D1.6.1 RAM[261]%D1.6.1 RAM[262]%D1.6.1;
set sp 261,
repeat 36 {
vmstep;
}
output;

View File

@@ -0,0 +1,20 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/08/FunctionCalls/StaticsTest/Sys.vm
// Tests that different functions, stored in two different
// class files, manipulate the static segment correctly.
function Sys.init 0
push constant 6
push constant 8
call Class1.set 2
pop temp 0 // Dumps the return value
push constant 23
push constant 15
call Class2.set 2
pop temp 0 // Dumps the return value
call Class1.get 0
call Class2.get 0
label WHILE
goto WHILE

View File

@@ -1,390 +0,0 @@
#include "code_writer.hpp"
code_writer::code_writer(std::string name)
{
file_name = name;
name.erase(name.find('.'));
name.append(".asm");
outfile.open(name);
}
void code_writer::write_assembly()
{
parser toparse(file_name);
toparse.parse();
commands = toparse.get_commands();
std::unordered_map<c_type,
std::function<void(std::string, int, bool)>>
write_map({{C_ARITHMETIC,
[this](std::string arg1, int arg2, bool arg3) {
this->write_arithmetic(arg1, arg2, arg3);
}},
{C_PUSH,
[this](std::string arg1, int arg2, bool arg3) {
this->write_push(arg1, arg2, arg3);
}},
{C_POP,
[this](std::string arg1, int arg2, bool arg3) {
this->write_pop(arg1, arg2, arg3);
}}});
for (auto curr : commands)
{
c_type write_type;
std::string instruction;
int index;
std::tie(write_type, instruction, index) = curr;
if (outfile.is_open())
{
write_map[write_type](instruction, index, this->dbg);
}
}
outfile.close();
}
void code_writer::write_push(std::string segment, int index, bool debug)
{
std::string toname = file_name;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug)
{
outfile << "// push " << segment << " " << index << std::endl;
}
if (segment == "constant")
{
outfile << "@" << index << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "static")
{
outfile << "@" << toname << "." << index << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "temp")
{
outfile << "@" << index + 5 << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "A=D" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 10;
}
}
void code_writer::write_pop(std::string segment, int index, bool debug)
{
std::string toname = file_name;
toname = toname.substr(toname.find_last_of('/')+1);
toname = toname.erase(toname.find('.'));
if (debug && segment != "constant")
{
outfile << "// pop " << segment << " " << index << std::endl;
}
if (segment == "static")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << toname << "." << index << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << which << std::endl
<< "M=D" << std::endl;
this->ins_no += 4;
}
else if (segment == "temp")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << index + 5 << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "@R13" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@R13" << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 12;
}
}
void code_writer::write_arithmetic(std::string comm, int index, bool debug)
{
std::unordered_map<std::string,
std::function<void(bool)>>
arith_mapic({
{"add",
[this](bool arg1) { this->write_add(arg1); }},
{"sub",
[this](bool arg1) { this->write_sub(arg1); }},
{"neg",
[this](bool arg1) { this->write_neg(arg1); }},
{"and",
[this](bool arg1) { this->write_and(arg1); }},
{"or",
[this](bool arg1) { this->write_or(arg1); }},
{"not",
[this](bool arg1) { this->write_not(arg1); }},
{"gt",
[this](bool arg1) { this->write_gt(arg1); }},
{"lt",
[this](bool arg1) { this->write_lt(arg1); }},
{"eq",
[this](bool arg1) { this->write_eq(arg1); }},
});
arith_mapic[comm](debug);
}
void code_writer::write_add(bool debug)
{
if (debug)
{
outfile << "// add" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D+M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_sub(bool debug)
{
if (debug)
{
outfile << "// sub" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=M-D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_neg(bool debug)
{
if (debug)
{
outfile << "// neg" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=-M" << std::endl;
this->ins_no += 3;
}
void code_writer::write_eq(bool debug)
{
if (debug)
{
outfile << "// eq" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JEQ" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_lt(bool debug)
{
if (debug)
{
outfile << "// lt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JLT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_gt(bool debug)
{
if (debug)
{
outfile << "// gt" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;JGT" << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_and(bool debug)
{
if (debug)
{
outfile << "// and" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D&M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_or(bool debug)
{
if (debug)
{
outfile << "// or" << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D|M" << std::endl;
this->ins_no += 6;
}
void code_writer::write_not(bool debug)
{
if (debug)
{
outfile << "// not" << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=!M" << std::endl;
this->ins_no += 3;
}

View File

@@ -1,28 +0,0 @@
#include "parser.hpp"
#include <functional>
class code_writer
{
private:
std::string file_name;
std::vector<vmcommand> commands;
std::ofstream outfile;
int ins_no = -1;
bool dbg = false;
public:
code_writer(std::string name);
void write_assembly();
void write_push(std::string segment, int index, bool debug);
void write_pop(std::string segment, int index, bool debug);
void write_arithmetic(std::string comm, int index, bool debug);
void write_add(bool debug);
void write_sub(bool debug);
void write_neg(bool debug);
void write_and(bool debug);
void write_or(bool debug);
void write_not(bool debug);
void write_eq(bool debug);
void write_lt(bool debug);
void write_gt(bool debug);
};

53
include/code_writer.hpp Normal file
View File

@@ -0,0 +1,53 @@
#include "parser.hpp"
#include <functional>
#include <string>
typedef std::vector<std::string> lots_of_files;
const std::unordered_map<std::string, std::string> operation_map({{"add", "M+D"},
{"sub", "M-D"},
{"neg", "-M"},
{"and", "D&M"},
{"or", "D|M"},
{"not", "!M"},
{"eq", "JEQ"},
{"lt", "JLT"},
{"gt", "LGT"}});
class code_writer
{
private:
lots_of_files files;
std::vector<vmcommand> commands;
std::ofstream outfile;
std::string current_file = "";
std::string current_function = "";
int ins_no = -1;
bool dbg = true;
bool is_dir = false;
public:
code_writer(lots_of_files name);
void write_assembly();
void write_push(std::string segment, int index, bool debug);
void write_push(std::string segment, bool debug);
void write_pop(std::string segment, int index, bool debug);
void write_pop(std::string segment, bool debug);
void write_arithmetic(std::string comm, int index, bool debug);
void write_add_sub_and_or(std::string op, bool debug);
void write_neg_not(std::string op, bool debug);
void write_eq_lt_gt(std::string op, bool debug);
void write_init(bool debug);
void write_label(std::string label, int index, bool debug);
void write_goto(std::string label, int index, bool debug);
void write_if(std::string label, int index, bool debug);
void write_call(std::string fun_name, int args, bool debug);
void write_return(bool debug);
void write_function(std::string fun_name, int locals, bool debug);
void write_frame_restore(std::string segment, int minus, bool debug);
};

View File

@@ -27,7 +27,7 @@ private:
std::vector<vmcommand> parsed;
public:
parser(std::string file) : input_file(file) {}
bool change_file(std::string name);
std::vector<vmcommand> get_commands();
c_type command_type(std::string com);
void parse();

View File

@@ -1,2 +0,0 @@
c++
debug

37
src/Main.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "../include/code_writer.hpp"
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main(int argc, char const *argv[])
{
lots_of_files files;
std::string input(argv[1]);
if (fs::is_directory(input))
{
files.push_back(input);
for (auto &entry : fs::directory_iterator(input))
{
if (entry.path().extension() == ".vm")
{
std::string vmfile = entry.path().string();
if (entry.path().filename() == "Sys.vm")
{
files.insert(files.begin() + 1, vmfile);
}
else
{
files.push_back(vmfile);
}
}
}
}
else
{
files.push_back(input);
}
code_writer toassembly(files);
toassembly.write_assembly();
return 0;
}

518
src/code_writer.cpp Normal file
View File

@@ -0,0 +1,518 @@
#include "../include/code_writer.hpp"
code_writer::code_writer(lots_of_files names)
{
this->files = names;
std::string outfile_name;
outfile_name = files.front();
if (files.size() > 1)
{
files.erase(files.begin());
std::string check = files.front();
if (check.substr(check.length() - 6) == "Sys.vm")
{
this->is_dir = true;
}
outfile_name = outfile_name + "/" + outfile_name;
}
else
{
outfile_name.erase(outfile_name.find('.'));
}
outfile_name.append(".asm");
outfile.open(outfile_name);
}
void code_writer::write_assembly()
{
std::unordered_map<c_type,
std::function<void(std::string, int, bool)>>
write_map({{C_ARITHMETIC,
[this](std::string arg1, int arg2, bool arg3) {
this->write_arithmetic(arg1, arg2, arg3);
}},
{C_PUSH,
[this](std::string arg1, int arg2, bool arg3) {
this->write_push(arg1, arg2, arg3);
}},
{C_POP,
[this](std::string arg1, int arg2, bool arg3) {
this->write_pop(arg1, arg2, arg3);
}},
{C_LABEL,
[this](std::string arg1, int arg2, bool arg3) {
this->write_label(arg1, arg2, arg3);
}},
{C_FUNCTION,
[this](std::string arg1, int arg2, bool arg3) {
this->write_function(arg1, arg2, arg3);
}},
{C_RETURN,
[this](std::string arg1, int arg2, bool arg3) {
this->write_return(arg3);
}},
{C_GOTO,
[this](std::string arg1, int arg2, bool arg3) {
this->write_goto(arg1, arg2, arg3);
}},
{C_IF,
[this](std::string arg1, int arg2, bool arg3) {
this->write_if(arg1, arg2, arg3);
}},
{C_CALL,
[this](std::string arg1, int arg2, bool arg3) {
this->write_call(arg1, arg2, arg3);
}}});
parser lets_parse;
this->write_init(this->dbg);
for (auto curr_file : this->files)
{
lets_parse.change_file(curr_file);
lets_parse.parse();
this->commands = lets_parse.get_commands();
this->current_file = curr_file;
for (auto curr : commands)
{
c_type write_type;
std::string instruction;
int index;
std::tie(write_type, instruction, index) = curr;
if (outfile.is_open())
{
write_map[write_type](instruction, index, this->dbg);
}
}
this->commands.clear();
}
outfile.close();
}
void code_writer::write_push(std::string segment, int index, bool debug)
{
std::string toname = this->current_file;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug)
{
outfile << "// push " << segment << " " << index << " " << this->ins_no << std::endl;
}
if (segment == "constant")
{
outfile << "@" << index << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "static")
{
outfile << "@" << toname << "." << index << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else if (segment == "temp")
{
outfile << "@" << index + 5 << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "A=D" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 10;
}
}
void code_writer::write_push(std::string segment, bool debug)
{
if (debug)
{
outfile << "// push " << segment << " " << this->ins_no << std::endl;
}
outfile << "@" << segment << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_pop(std::string segment, int index, bool debug)
{
std::string toname = this->current_file;
toname = toname.substr(toname.find_last_of('/') + 1);
toname = toname.erase(toname.find('.'));
if (debug && segment != "constant")
{
outfile << "// pop " << segment << " " << index << " " << this->ins_no << std::endl;
}
if (segment == "static")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << toname << "." << index << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "pointer")
{
std::string which = (index == 0) ? "THIS" : "THAT";
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << which << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else if (segment == "temp")
{
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << index + 5 << std::endl
<< "M=D" << std::endl;
this->ins_no += 5;
}
else
{
std::string which;
if (segment == "local")
{
which = "LCL";
}
else if (segment == "argument")
{
which = "ARG";
}
else if (segment == "this")
{
which = "THIS";
}
else if (segment == "that")
{
which = "THAT";
}
outfile << "@" << which << std::endl
<< "D=M" << std::endl
<< "@" << index << std::endl
<< "D=D+A" << std::endl
<< "@R13" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@R13" << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 12;
}
}
void code_writer::write_pop(std::string segment, bool debug)
{
if (debug)
{
outfile << "// pop " << segment << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << segment << std::endl
<< "A=M" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_arithmetic(std::string comm, int index, bool debug)
{
std::unordered_map<std::string,
std::function<void(std::string, bool)>>
arith_mapic({
{"add",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"sub",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"and",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"or",
[this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }},
{"neg",
[this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }},
{"not",
[this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }},
{"gt",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
{"lt",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
{"eq",
[this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }},
});
arith_mapic[comm](comm, debug);
}
void code_writer::write_add_sub_and_or(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=" << operation_map.at(op) << std::endl;
this->ins_no += 6;
}
void code_writer::write_neg_not(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=" << operation_map.at(op) << std::endl;
this->ins_no += 3;
}
void code_writer::write_eq_lt_gt(std::string op, bool debug)
{
if (debug)
{
outfile << "// " << op << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "A=A-1" << std::endl
<< "D=M-D" << std::endl;
this->ins_no += 5;
outfile << "@" << this->ins_no + 6 << std::endl
<< "D;" << operation_map.at(op) << std::endl
<< "D=0" << std::endl;
this->ins_no += 3;
outfile << "@" << this->ins_no + 4 << std::endl
<< "0;JMP" << std::endl
<< "D=-1" << std::endl
<< "@SP" << std::endl
<< "A=M-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
}
void code_writer::write_init(bool debug)
{
if (debug)
{
outfile << "// bootstrap code"
<< " " << this->ins_no << std::endl;
}
outfile << "@256" << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "M=D" << std::endl;
this->ins_no += 4;
if (this->is_dir)
{
outfile << "// Sys.init defined adding function call..."
<< " " << this->ins_no << std::endl;
this->write_call("Sys.init", 0, debug);
}
}
void code_writer::write_call(std::string fun_name, int args, bool debug)
{
if (debug)
{
outfile << "// call" << fun_name << " " << args << " " << this->ins_no << std::endl;
}
std::string curr_ins = std::to_string(this->ins_no);
std::string ret_label("ret." + fun_name + "$" + curr_ins);
outfile << "@" << ret_label << std::endl
<< "D=A" << std::endl
<< "@SP" << std::endl
<< "AM=M+1" << std::endl
<< "A=A-1" << std::endl
<< "M=D" << std::endl;
this->ins_no += 6;
this->write_push("LCL", debug);
this->write_push("ARG", debug);
this->write_push("THIS", debug);
this->write_push("THAT", debug);
outfile << "@SP" << std::endl
<< "D=M" << std::endl
<< "@5" << std::endl
<< "D=D-A" << std::endl
<< "@" << args << std::endl
<< "D=D-A" << std::endl
<< "@ARG" << std::endl
<< "M=D" << std::endl
<< "@SP" << std::endl
<< "D=M" << std::endl
<< "@LCL" << std::endl
<< "M=D" << std::endl
<< "@" << fun_name << std::endl
<< "0;JMP" << std::endl
<< "(" << ret_label << ")" << std::endl;
this->ins_no += 14;
}
void code_writer::write_label(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// label " << label << " " << this->ins_no << std::endl;
}
outfile << "(" << current_function << "$" << label << ")" << std::endl;
}
void code_writer::write_goto(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// goto " << label << " " << this->ins_no << std::endl;
}
outfile << "@" << current_function << "$" << label << std::endl
<< "0;JMP" << std::endl;
this->ins_no += 2;
}
void code_writer::write_function(std::string fun_name, int locals, bool debug)
{
if (debug)
{
outfile << "// function " << fun_name << " " << locals << " " << this->ins_no << std::endl;
}
current_function = fun_name;
outfile << "(" << fun_name << ")" << std::endl;
for (int l = 0; l < locals; l++)
{
this->write_push("constant", 0, debug);
}
}
void code_writer::write_return(bool debug)
{
if (debug)
{
outfile << "// return " << current_function << " " << this->ins_no << std::endl;
}
outfile << "@LCL" << std::endl
<< "D=M" << std::endl
<< "@R7" << std::endl
<< "M=D" << std::endl
<< "@5" << std::endl
<< "A=D-A" << std::endl
<< "D=M" << std::endl
<< "@R14" << std::endl
<< "M=D" << std::endl;
this->ins_no += 9;
this->write_pop("ARG", debug);
outfile << "@ARG" << std::endl
<< "D=M" << std::endl
<< "@SP" << std::endl
<< "M=D+1" << std::endl;
this->ins_no += 4;
this->write_frame_restore("THAT", 1, debug);
this->write_frame_restore("THIS", 2, debug);
this->write_frame_restore("ARG", 3, debug);
this->write_frame_restore("LCL", 4, debug);
outfile << "@R14" << std::endl
<< "A=M" << std ::endl
<< "0;JMP" << std::endl;
this->ins_no += 3;
}
void code_writer::write_frame_restore(std::string segment, int minus, bool debug)
{
if (debug)
{
outfile << "// restoring " << segment << " " << this->ins_no << std::endl;
}
outfile << "@R7" << std::endl
<< "D=M" << std::endl
<< "@" << minus << std::endl
<< "A=D-A" << std::endl
<< "D=M" << std::endl
<< "@" << segment << std::endl
<< "M=D" << std::endl;
this->ins_no += 7;
}
void code_writer::write_if(std::string label, int index, bool debug)
{
if (debug)
{
outfile << "// if " << label << " " << this->ins_no << std::endl;
}
outfile << "@SP" << std::endl
<< "AM=M-1" << std::endl
<< "D=M" << std::endl
<< "@" << current_function << "$" << label << std::endl
<< "D;JNE" << std::endl;
this->ins_no += 5;
}

View File

@@ -1,4 +1,4 @@
#include "parser.hpp"
#include "../include/parser.hpp"
c_type parser::command_type(std::string com)
{
@@ -76,3 +76,18 @@ std::vector<vmcommand> parser::get_commands()
{
return this->parsed;
}
bool parser::change_file(std::string name)
{
this->parsed.clear();
this->input_file = name;
if (this->parsed.size() == 0 && input_file == name)
{
return true;
}
else
{
return false;
}
}

View File

@@ -1,4 +1,4 @@
#include "vutility.hpp"
#include "../include/vutility.hpp"
std::vector<std::string> vutility::split(std::string str, char delimit)
{
@@ -14,14 +14,12 @@ std::vector<std::string> vutility::split(std::string str, char delimit)
std::string vutility::trim(std::string str)
{
if (str.substr(0, 2) == "//")
if (str.find('/') != std::string::npos) // comments
{
str.erase();
str.erase(str.find('/'));
}
else
{
str.erase(0, str.find_first_not_of(" \r\t\v\n")); //prefixing
str.erase(str.find_last_not_of(" \r\t\v\n") + 1); //surfixing}
}
return str;
}