mirror of
https://gitlab.com/VoidEUW/stacat.git
synced 2025-12-12 15:18:41 +00:00
uploaded current state of stacat
This commit is contained in:
7
src/config.h
Normal file
7
src/config.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define DEBUG true
|
||||
#define STACAT_VERSION "1.0.0"
|
||||
|
||||
#endif
|
||||
89
src/interpreter/interpreter.cpp
Normal file
89
src/interpreter/interpreter.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "interpreter.h"
|
||||
#include "../output.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace debug;
|
||||
using namespace error;
|
||||
|
||||
Interpreter::Interpreter(string data, string filename) {
|
||||
// interpreter data
|
||||
this->data = data;
|
||||
this->stack = list<size_t>();
|
||||
this->ostream = list<char>();
|
||||
|
||||
// interpreter states
|
||||
this->comment = false;
|
||||
this->filename = filename;
|
||||
this->line = 1;
|
||||
this->column = 1;
|
||||
this->before_command = 0;
|
||||
}
|
||||
|
||||
void Interpreter::run() {
|
||||
// run interpreter
|
||||
for (char command : this->data) {
|
||||
this->interpret(command);
|
||||
}
|
||||
this->ostream.reverse();
|
||||
|
||||
// clear stack
|
||||
this->stack.clear();
|
||||
}
|
||||
|
||||
void Interpreter::interpret(char command) {
|
||||
// evaluate command
|
||||
switch (command) {
|
||||
case '>':
|
||||
this->push();
|
||||
break;
|
||||
case '^':
|
||||
this->clone();
|
||||
break;
|
||||
case '+':
|
||||
this->add();
|
||||
break;
|
||||
case '-':
|
||||
this->sub();
|
||||
break;
|
||||
case '*':
|
||||
this->mul();
|
||||
break;
|
||||
case '!':
|
||||
if (!this->comment) {
|
||||
this->print();
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
this->input();
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
case '\n':
|
||||
this->line++;
|
||||
this->column = 1;
|
||||
this->comment = false;
|
||||
break;
|
||||
case '\t':
|
||||
this->column += 4;
|
||||
break;
|
||||
case '_':
|
||||
this->comment = !this->comment;
|
||||
break;
|
||||
default:
|
||||
if (!this->comment) {
|
||||
throwError(UNKNOWN_INSTRUCTION, this->filename, this->line, this->column, command, __LINE__, __FILE__);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string Interpreter::getostream() {
|
||||
string output = "";
|
||||
for (char c : this->ostream) {
|
||||
output += c;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
55
src/interpreter/interpreter.h
Normal file
55
src/interpreter/interpreter.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERPRETER_H
|
||||
#define INTERPRETER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
class Interpreter {
|
||||
public:
|
||||
// constructor
|
||||
Interpreter(std::string data, std::string filename);
|
||||
|
||||
// methods
|
||||
void run();
|
||||
std::string getostream();
|
||||
|
||||
private:
|
||||
// interpreter data
|
||||
std::string data;
|
||||
std::list<size_t> stack;
|
||||
std::list<char> ostream;
|
||||
|
||||
// interpreter states
|
||||
bool comment;
|
||||
std::string filename;
|
||||
int line;
|
||||
int column;
|
||||
char before_command;
|
||||
|
||||
// methods
|
||||
void interpret(char command);
|
||||
|
||||
void push();
|
||||
void clone();
|
||||
void add();
|
||||
void sub();
|
||||
void mul();
|
||||
|
||||
void print();
|
||||
void input();
|
||||
};
|
||||
|
||||
class Function {
|
||||
public:
|
||||
// constructor
|
||||
Function(std::string name, std::string data);
|
||||
|
||||
// methods
|
||||
void run();
|
||||
private:
|
||||
// function data
|
||||
std::string name;
|
||||
std::string data;
|
||||
};
|
||||
|
||||
#endif
|
||||
46
src/interpreter/operations.cpp
Normal file
46
src/interpreter/operations.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "interpreter.h"
|
||||
#include "../output.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace debug;
|
||||
using namespace error;
|
||||
|
||||
void Interpreter::push() {
|
||||
this->stack.push_back(1);
|
||||
this->column++;
|
||||
}
|
||||
|
||||
void Interpreter::clone() {
|
||||
this->stack.push_back(this->stack.back());
|
||||
this->column++;
|
||||
}
|
||||
|
||||
void Interpreter::add() {
|
||||
long long value = this->stack.back();
|
||||
this->stack.pop_back();
|
||||
this->stack.back() += value;
|
||||
}
|
||||
|
||||
void Interpreter::sub() {
|
||||
long long value = this->stack.back();
|
||||
this->stack.pop_back();
|
||||
this->stack.back() -= value;
|
||||
}
|
||||
|
||||
void Interpreter::mul() {
|
||||
long long value = this->stack.back();
|
||||
this->stack.pop_back();
|
||||
this->stack.back() *= value;
|
||||
}
|
||||
|
||||
void Interpreter::print() {
|
||||
this->ostream.push_back(this->stack.back());
|
||||
this->stack.pop_back();
|
||||
this->column++;
|
||||
}
|
||||
|
||||
void Interpreter::input() {
|
||||
log("Inputting");
|
||||
}
|
||||
79
src/main.cpp
Normal file
79
src/main.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "config.h"
|
||||
#include "main.h"
|
||||
#include "output.h"
|
||||
#include "interpreter/interpreter.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace debug;
|
||||
using namespace error;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// check arguments
|
||||
program::checkargs(argc, argv);
|
||||
// read arguments
|
||||
ProgramMode mode = program::readargs(argc, argv);
|
||||
// check interpreter mode
|
||||
switch (mode) {
|
||||
case FILE_INTERPRETER:
|
||||
log("Running file interpreter");
|
||||
program::run(argv[1]);
|
||||
break;
|
||||
case CONSOLE_INTERPRETER:
|
||||
log("Running console interpreter");
|
||||
program::run();
|
||||
break;
|
||||
case MANUAL:
|
||||
log("Displaying manual");
|
||||
program::man();
|
||||
break;
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
namespace program {
|
||||
|
||||
void run(char* filename) {
|
||||
// prepare interpreter
|
||||
string data = utils::readfile(filename);
|
||||
Interpreter interpreter(data, filename);
|
||||
|
||||
// run interpreter
|
||||
interpreter.run();
|
||||
|
||||
// get output
|
||||
string ostream = interpreter.getostream();
|
||||
program::outputconsole(ostream);
|
||||
}
|
||||
|
||||
void run() {
|
||||
Interpreter interpreter("data", "console");
|
||||
interpreter.run();
|
||||
}
|
||||
|
||||
void checkargs(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
throwError(WRONG_ARGUMENT_COUNT, "Not enough arguments", __LINE__, __FILE__);
|
||||
}
|
||||
else if (argc > 2) {
|
||||
throwError(WRONG_ARGUMENT_COUNT, "Too many arguments", __LINE__, __FILE__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ProgramMode readargs(int argc, char* argv[]) {
|
||||
log("Reading arguments");
|
||||
return FILE_INTERPRETER;
|
||||
}
|
||||
|
||||
void outputconsole(string ostream) {
|
||||
cout << ostream << endl;
|
||||
}
|
||||
|
||||
void man() {
|
||||
log("Displaying manual");
|
||||
cout << "Usage: stacat [filename]" << endl;
|
||||
}
|
||||
}
|
||||
25
src/main.h
Normal file
25
src/main.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
int main(int argc, char* argv[]);
|
||||
|
||||
typedef enum ProgramMode {
|
||||
FILE_INTERPRETER,
|
||||
CONSOLE_INTERPRETER,
|
||||
MANUAL
|
||||
} ProgramMode;
|
||||
|
||||
namespace program {
|
||||
// main.cpp
|
||||
void run(char* filename);
|
||||
void run();
|
||||
void checkargs(int argc, char* argv[]);
|
||||
ProgramMode readargs(int argc, char* argv[]);
|
||||
void outputconsole(std::string ostream);
|
||||
|
||||
void man();
|
||||
}
|
||||
|
||||
#endif
|
||||
76
src/output.cpp
Normal file
76
src/output.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "config.h"
|
||||
#include "output.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace debug {
|
||||
|
||||
void log(string message) {
|
||||
if (DEBUG) {
|
||||
cerr << "(\033[1;33mDEBUG\033[0m)\033[1;34mLOG\033[0m: " << message << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void log(string message, int line) {
|
||||
if (DEBUG) {
|
||||
cerr << "(\033[1;33mDEBUG\033[0m)\033[1;34mLOG\033[0m: " << message << " at line " << line << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void log(string message, int line, int column, int codeLine) {
|
||||
if (DEBUG) {
|
||||
cerr << "(\033[1;33mDEBUG\033[0m)\033[1;34mLOG\033[0m: " << message << " at line " << line << " at column " << column << " at code line " << codeLine << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace error {
|
||||
|
||||
void throwError(RuntimeError error, const string message, int line, const string file) {
|
||||
string errorMessage = getRuntimeError(error);
|
||||
if (DEBUG) {
|
||||
cerr << "(\033[1;33mDEBUG\033[0m)\033[1;31mERROR\033[0m: " << errorMessage << " at file '" << file << "' at line " << line << endl;
|
||||
}
|
||||
else {
|
||||
cerr << "\033[1;31mERROR\033[0m: " << errorMessage << endl;
|
||||
}
|
||||
}
|
||||
|
||||
string getRuntimeError(RuntimeError error) {
|
||||
switch (error) {
|
||||
case WRONG_ARGUMENT_COUNT:
|
||||
return "Wrong argument count";
|
||||
case WRONG_FILE_EXTENSION:
|
||||
return "Wrong file extension";
|
||||
case FILE_NOT_FOUND:
|
||||
return "File not found";
|
||||
case FILE_READ_ERROR:
|
||||
return "File read error";
|
||||
case FILE_EMPTY_ERROR:
|
||||
return "File empty error";
|
||||
}
|
||||
}
|
||||
|
||||
void throwError(InterpreterError error, const string file, const int line, const int column, const char instruction, const int codeline, const string sourcefile) {
|
||||
string errorMessage = getInterpreterError(error);
|
||||
if (DEBUG) {
|
||||
cerr << "\033[1;35m" << file << ":l" << line << ":c" << column << "\033[0m\033[1;35m '" << instruction << "':\033[0m \033[1;31mERROR\033[0m " << "I DOAN UNDERSTAND DIS! (at line " << codeline << " at file '" << sourcefile << "')" << endl;
|
||||
}
|
||||
else {
|
||||
cerr << "\033[1;35m" << file << ":l" << line << ":c" << column << "\033[0m\033[1;35m '" << instruction << "':\033[0m \033[1;31mERROR\033[0m " << "I DOAN UNDERSTAND DIS! " << endl;
|
||||
}
|
||||
}
|
||||
|
||||
string getInterpreterError(InterpreterError error) {
|
||||
switch (error) {
|
||||
case UNKNOWN_INSTRUCTION:
|
||||
return "Unknown instruction";
|
||||
case POINTER_OUT_OF_BOUNDS:
|
||||
return "Pointer out of bounds";
|
||||
case INVALID_VALUE:
|
||||
return "Invalid value";
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/output.h
Normal file
31
src/output.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
typedef enum RuntimeError {
|
||||
WRONG_ARGUMENT_COUNT,
|
||||
WRONG_FILE_EXTENSION,
|
||||
FILE_NOT_FOUND,
|
||||
FILE_READ_ERROR,
|
||||
FILE_EMPTY_ERROR
|
||||
} RuntimeError;
|
||||
|
||||
typedef enum InterpreterError {
|
||||
UNKNOWN_INSTRUCTION,
|
||||
POINTER_OUT_OF_BOUNDS,
|
||||
INVALID_VALUE
|
||||
} InterpreterError;
|
||||
|
||||
namespace debug {
|
||||
void log(std::string message);
|
||||
void log(std::string message, int line);
|
||||
void log(std::string message, int line, int column, int codeLine);
|
||||
}
|
||||
|
||||
namespace error {
|
||||
void throwError(RuntimeError error, const std::string message, int line, const std::string file);
|
||||
std::string getRuntimeError(RuntimeError error);
|
||||
void throwError(InterpreterError error, const std::string file, const int line, const int column, const char instruction, const int codeline, const std::string sourcefile);
|
||||
std::string getInterpreterError(InterpreterError error);
|
||||
}
|
||||
|
||||
#endif
|
||||
36
src/utils/readfile.cpp
Normal file
36
src/utils/readfile.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "readfile.h"
|
||||
#include "utils.h"
|
||||
#include "../output.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace debug;
|
||||
using namespace error;
|
||||
|
||||
namespace utils {
|
||||
|
||||
string readfile(const char* filename) {
|
||||
ifstream file(filename);
|
||||
if (!checkfile(file)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
string data, line;
|
||||
while (getline(file, line)) {
|
||||
data += line;
|
||||
data += '\n';
|
||||
}
|
||||
data.pop_back();
|
||||
file.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
bool checkfile(ifstream& file) {
|
||||
if (!file.is_open()) {
|
||||
throwError(FILE_NOT_FOUND, "File not found", __LINE__, __FILE__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
9
src/utils/readfile.h
Normal file
9
src/utils/readfile.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef READFILE_H
|
||||
#define READFILE_H
|
||||
|
||||
#define FILE_EXTENSION ".scat"
|
||||
|
||||
#define MAX_FILE_LENGTH 0x0FFFFFFFUL
|
||||
#define MAX_FILE_NAME_LENGTH 256
|
||||
|
||||
#endif
|
||||
12
src/utils/utils.h
Normal file
12
src/utils/utils.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace utils {
|
||||
// readfile.cpp
|
||||
std::string readfile(const char* filename);
|
||||
bool checkfile(std::ifstream& file);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user