moved C/C++ implementation to separate folder
This commit is contained in:
35
Cati/Makefile
Executable file
35
Cati/Makefile
Executable file
@ -0,0 +1,35 @@
|
||||
CXX:=g++
|
||||
CFLAGS:=-O0 -ggdb -std=c++17
|
||||
CPPFLAGS:=-D DEBUG
|
||||
LDLIBS:=
|
||||
LDFLAGS:=
|
||||
COMP:=$(CXX) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
OBJD:=obj/
|
||||
SRCD:=src/
|
||||
SRC:=main.cpp lexer.cpp algo.cpp
|
||||
SRC:=$(addprefix ${SRCD},${SRC})
|
||||
OBJ:=$(subst .cpp,.o,$(subst ${SRCD},${OBJD},${SRC}))
|
||||
|
||||
OUTPUT:=ati.out
|
||||
|
||||
.PHONY: main clean run
|
||||
|
||||
main: ${OBJ}
|
||||
${COMP} ${OBJ} -o ${OUTPUT}
|
||||
|
||||
obj/%.o: src/%.cpp
|
||||
${COMP} -c $< -o ${OBJD}/$*.o
|
||||
|
||||
clean:
|
||||
-rm ${OBJD}/*
|
||||
-rm ./${OUTPUT}
|
||||
|
||||
run:
|
||||
./${OUTPUT}
|
||||
|
||||
gdb:
|
||||
sudo gdb --directory=./src -p $(shell pgrep ${OUTPUT})
|
||||
|
||||
algo:
|
||||
make -C debug/
|
0
Cati/obj/.placeholder
Normal file
0
Cati/obj/.placeholder
Normal file
36
Cati/src/JokerTao.cpp
Normal file
36
Cati/src/JokerTao.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "JokerTao.h"
|
||||
|
||||
unsigned int JokerTao::id_ = JOKERTAO::END;
|
||||
|
||||
namespace jt{
|
||||
inline std::vector<JokerTao> table;
|
||||
|
||||
unsigned findf_relationship(int attr_, std::string value_){
|
||||
unsigned last_id = JOKERTAO::END - 1;
|
||||
for(auto &&i : table[i]){
|
||||
if(i.id == last_id){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i.attr == attr && i.value == value_){
|
||||
return i.index;
|
||||
}
|
||||
}
|
||||
|
||||
return JOKERTAO::INVALID;
|
||||
}
|
||||
|
||||
unsigned find_attribute(unsigned id_, JokerTao* attr_, unsigned index_ = 0){
|
||||
for(auto &&i : table[i]){
|
||||
if(i.id != id_){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i.attr == attr){
|
||||
return i.index;
|
||||
}
|
||||
}
|
||||
|
||||
return JOKERTAO::INVALID;
|
||||
}
|
||||
}
|
33
Cati/src/JokerTao.h
Normal file
33
Cati/src/JokerTao.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
enum JOKERTAO{
|
||||
INVALID,
|
||||
NAME,
|
||||
VALUE
|
||||
END
|
||||
};
|
||||
|
||||
struct JokerTao{
|
||||
unsigned id;
|
||||
JokerTao *attr;
|
||||
unsigned index;
|
||||
std::string value; //void* value = nullptr;
|
||||
|
||||
inline unsigned last_id(){ return id__; }
|
||||
JokerTao(attr_ = nullptr, value_ = "", id_ = id__++, index_ = 0) :
|
||||
id(id_), attr(attr_), index(index_), value(value_){
|
||||
}
|
||||
delete JokerTao();
|
||||
|
||||
private:
|
||||
static unsigned id__;
|
||||
};
|
||||
|
||||
namespace jt{
|
||||
extern std::vector<JokerTao> table;
|
||||
|
||||
unsigned findf_relationship(unsigned attr_, std::string value_);
|
||||
unsigned find_attribute(unsigned index_, JokerTao* attr_, unsigned index_ = 0);
|
||||
}
|
240
Cati/src/algo.cpp
Normal file
240
Cati/src/algo.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
#include "algo.h"
|
||||
|
||||
namespace algo{
|
||||
/* VARS */
|
||||
inline std::stack<struct frame> callstack;
|
||||
inline std::unordered_map<std::string, std::string> vars;
|
||||
/**/
|
||||
|
||||
bool init(){
|
||||
const char *const *c = standard_vars-1;
|
||||
while((c++, *c != NULL)){
|
||||
vars[*c] = EMPTY_CELL;
|
||||
}
|
||||
callstack.emplace();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void assign(const std::string &name, const std::string& val){
|
||||
vars[name] = val;
|
||||
//unsigned index = findf_relationship(NAME, v[ALGO::DESTINATION]);
|
||||
//if(index == JOKERTAO::INVALID){
|
||||
// jt::table.emplace_back(JOKERTAO::NAME, v[ALGO::DESTINATION]);
|
||||
// jt::table.emplace_back(JOKERTAO::VALUE, v[ALGO::VALUE], 0);
|
||||
//}else{
|
||||
// jt[index].find_attribute()
|
||||
//}
|
||||
}
|
||||
|
||||
void pop(unsigned &head){
|
||||
if(callstack.size() == 1){
|
||||
#ifdef DEBUG
|
||||
printf(YELLOW "Return on empty callstack: exiting.\n" NORMAL);
|
||||
#endif
|
||||
raise(SIGINT);
|
||||
}
|
||||
callstack.pop();
|
||||
head = callstack.top().bp + 1;
|
||||
}
|
||||
void push(const unsigned &head){
|
||||
callstack.top().bp = head;
|
||||
callstack.emplace();
|
||||
}
|
||||
|
||||
std::string arref(std::string s){
|
||||
for(int i = s.size()-1, last = i; i >= 0; i--){
|
||||
if(s[i] == '-'){
|
||||
s.replace(i+1, last-i, deref(s.substr(i+1, last-i)));
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string deref(std::string s){
|
||||
s = arref(s);
|
||||
return (vars.find(s) != vars.end()) ? deref(vars[s]) : s;
|
||||
}
|
||||
|
||||
bool jump(unsigned &head, const jmp &do_jump, const std::string &dest, const char &push){
|
||||
bool ret = false;
|
||||
switch(do_jump){
|
||||
case algo::jmp::nop:
|
||||
break;
|
||||
case algo::jmp::jmp:
|
||||
algo::call(head, dest, (push != algo::EMPTY_CELL));
|
||||
ret = true;
|
||||
break;
|
||||
case algo::jmp::je:
|
||||
if(algo::vars["eval"] == algo::true_){
|
||||
algo::call(head, dest, (push != algo::EMPTY_CELL));
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case algo::jmp::jne:
|
||||
if(algo::vars["eval"] == algo::false_){
|
||||
algo::call(head, dest, (push != algo::EMPTY_CELL));
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if(ret){
|
||||
printf(MAGENTA "Jumped to '%s' (%s). " NORMAL, dest.c_str(), algo::deref(dest).c_str());
|
||||
}
|
||||
printf(MAGENTA "Head at %d. " NORMAL, head);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void call(unsigned &head, const std::string &dest, const bool &is_push){
|
||||
#ifdef DEBUG
|
||||
long debug_stacklen = algo::callstack.size();
|
||||
#endif
|
||||
if(dest == "return"){
|
||||
pop(head);
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
if(is_push){ push(head); }
|
||||
|
||||
try{
|
||||
head = std::stoi(deref(dest));
|
||||
}catch(...){
|
||||
#ifdef DEBUG
|
||||
printf("Invalid jump destination '%s'", dest.c_str());
|
||||
#endif
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
RETURN:
|
||||
#ifdef DEBUG
|
||||
if(algo::callstack.size() != debug_stacklen){
|
||||
printf(YELLOW "[Stack: %ld->%ld] " NORMAL, debug_stacklen, algo::callstack.size());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int aint(std::string s){
|
||||
static const char c[] = "0123456789";
|
||||
int i = 0;
|
||||
bool sign = true;
|
||||
while(true){
|
||||
switch(s[i]){
|
||||
case '-':
|
||||
sign = !(sign xor false);
|
||||
++i;
|
||||
continue;
|
||||
case '+':
|
||||
sign = !(sign xor true);
|
||||
++i;
|
||||
continue;
|
||||
default:
|
||||
goto BR;
|
||||
}
|
||||
}
|
||||
BR:
|
||||
s.erase(0, i);
|
||||
|
||||
for(i = 0; i < s.size(); i++){
|
||||
bool is_any = false;
|
||||
for(int h = 0, end2 = sizeof(c)-1; h < end2; h++){
|
||||
if(s[i] == c[h]){
|
||||
is_any = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(not is_any){
|
||||
s.erase(i, 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
if(s == ""){ s = '0'; }
|
||||
|
||||
return std::stoi(s) * (sign ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
void do_eval(const std::string &opr1, char oper, const std::string &opr2){ // convert to use assign()
|
||||
#define CASECHAR(c){ \
|
||||
case (char)(*#c):\
|
||||
vars["eval"] = std::to_string(aint(deref(opr1)) c aint(deref(opr2))); \
|
||||
}
|
||||
#define CASELCHAR(c){ \
|
||||
case (char)(*#c):\
|
||||
aint(deref(opr1)) c aint(deref(opr2)) ? (vars["eval"] = true_) : (vars["eval"] = false_); \
|
||||
}
|
||||
//is_cmp = (oper == EMPTY_CELL);
|
||||
vars["eval"] = "";
|
||||
switch(oper){
|
||||
case EMPTY_CELL:
|
||||
vars["eval"] = deref(opr1);
|
||||
return;
|
||||
case '.':
|
||||
vars["eval"] = deref(opr1) + deref(opr2);
|
||||
return;
|
||||
case '\'':
|
||||
vars["eval"] = deref(opr1).substr(0, opr1.size()-aint(deref(opr2)));
|
||||
return;
|
||||
CASECHAR(-)
|
||||
return;
|
||||
CASECHAR(+)
|
||||
return;
|
||||
CASECHAR(/)
|
||||
return;
|
||||
CASECHAR(*)
|
||||
return;
|
||||
CASECHAR(%)
|
||||
return;
|
||||
CASELCHAR(<)
|
||||
return;
|
||||
CASELCHAR(>)
|
||||
return;
|
||||
case '=':
|
||||
aint(deref(opr1)) == aint(deref(opr2)) ? (vars["eval"] = true_) : (vars["eval"] = false_); \
|
||||
return;
|
||||
CASELCHAR(|)
|
||||
return;
|
||||
CASELCHAR(&)
|
||||
return;
|
||||
CASELCHAR(^)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//int aint(std::string s){
|
||||
// static const char c[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; // ?!
|
||||
// bool sign = true;
|
||||
// int roof = 1;
|
||||
//
|
||||
// for(int i = 0, int end = s.size(); i < end; i++){
|
||||
// int h = 0;
|
||||
// for(int e = sizeof(c)-1; h < e; h++){
|
||||
// if(c[h] == s[i]){
|
||||
// while(pow(2, roof) < h){
|
||||
// ++roof;
|
||||
// }
|
||||
// goto CONT;
|
||||
// }
|
||||
// }
|
||||
// switch(s[i]){
|
||||
// case '-':
|
||||
// sign = !(sign xor false);
|
||||
// s.rease(i, 1);
|
||||
// --i;
|
||||
// continue;
|
||||
// case '+':
|
||||
// sign = !(sign xor true);
|
||||
// s.rease(i, 1);
|
||||
// --i;
|
||||
// continue;
|
||||
// default:
|
||||
// s[i] = '0';
|
||||
// continue;
|
||||
// }
|
||||
// CONT:
|
||||
// }
|
||||
//}
|
76
Cati/src/algo.h
Normal file
76
Cati/src/algo.h
Normal file
@ -0,0 +1,76 @@
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#ifdef DEBUG
|
||||
# include "debug.h"
|
||||
#endif
|
||||
|
||||
namespace algo{
|
||||
/* CONST */
|
||||
enum{
|
||||
// LINE,
|
||||
JUMP,
|
||||
DESTINATION,
|
||||
ASSIGNMENT,
|
||||
OPR1,
|
||||
OPERATOR,
|
||||
OPR2,
|
||||
COMMENT
|
||||
};
|
||||
|
||||
enum class jmp{
|
||||
nop,
|
||||
jmp,
|
||||
je,
|
||||
jne
|
||||
};
|
||||
|
||||
const char EMPTY_CELL = '0';
|
||||
|
||||
const char true_[] = "TRUE";
|
||||
const char false_[] = "FALSE";
|
||||
|
||||
struct frame{
|
||||
unsigned bp;
|
||||
};
|
||||
|
||||
const char* const standard_vars[] = {
|
||||
"eval",
|
||||
"ret",
|
||||
"argv-0",
|
||||
"argv-1",
|
||||
"argv-2",
|
||||
"argv-3",
|
||||
"argv-4",
|
||||
"argv-5",
|
||||
"argv-6",
|
||||
"argv-7",
|
||||
"argv-8",
|
||||
"argv-9",
|
||||
NULL
|
||||
};
|
||||
/**/
|
||||
|
||||
/* VARS */
|
||||
extern std::stack<struct frame> callstack;
|
||||
extern std::unordered_map<std::string, std::string> vars;
|
||||
/**/
|
||||
|
||||
bool init();
|
||||
|
||||
std::string arref(std::string s);
|
||||
std::string deref(std::string s);
|
||||
int aint(std::string s);
|
||||
|
||||
void assign(const std::string &name, const std::string& val);
|
||||
|
||||
void do_eval(const std::string &opr1, char oper, const std::string &opr2);
|
||||
|
||||
void pop(unsigned &head);
|
||||
void push(const unsigned &head);
|
||||
|
||||
bool jump(unsigned &head, const jmp &do_jump, const std::string &dest, const char &push);
|
||||
void call(unsigned &head, const std::string &dest, const bool &is_push);
|
||||
}
|
23
Cati/src/debug.h
Normal file
23
Cati/src/debug.h
Normal file
@ -0,0 +1,23 @@
|
||||
#define DEBUG_COLOR
|
||||
|
||||
#ifdef DEBUG_COLOR
|
||||
# define NORMAL "\033[0m"
|
||||
# define BOLD "\033[1m"
|
||||
# define RED "\033[31m"
|
||||
# define GREEN "\033[32m"
|
||||
# define YELLOW "\033[33m"
|
||||
# define BLUE "\033[34m"
|
||||
# define MAGENTA "\033[35m"
|
||||
# define CYAN "\033[36m"
|
||||
# define WHITE "\033[37m"
|
||||
#else
|
||||
# define NORMAL ""
|
||||
# define BOLD ""
|
||||
# define RED ""
|
||||
# define GREEN ""
|
||||
# define YELLOW ""
|
||||
# define BLUE ""
|
||||
# define MAGENTA ""
|
||||
# define CYAN ""
|
||||
# define WHITE ""
|
||||
#endif
|
87
Cati/src/lexer.cpp
Normal file
87
Cati/src/lexer.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "lexer.h"
|
||||
|
||||
#include "rapidcsv.h"
|
||||
#include "algo.h"
|
||||
|
||||
|
||||
inline unsigned long long instruction_counter = 1;
|
||||
|
||||
void lex_file(const char* const f){
|
||||
rapidcsv::Document doc(f, rapidcsv::LabelParams(-1, -1),
|
||||
rapidcsv::SeparatorParams(';')
|
||||
);
|
||||
std::vector<std::string> buf;
|
||||
|
||||
for(unsigned head = 1, end = doc.GetRowCount()+1; head < end; head++){
|
||||
#ifdef DEBUG
|
||||
printf(BOLD BLUE "%0#6llx" NORMAL "|", instruction_counter++);
|
||||
printf(BOLD "%s:%d: " NORMAL, f, head);
|
||||
#endif
|
||||
const std::string c = doc.GetCell<std::string>(0, head-1);
|
||||
if(c[0] == '"'){ // skip comments
|
||||
#ifdef DEBUG
|
||||
printf(GREEN "Comment: %s\n" NORMAL, c.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
buf = doc.GetRow<std::string>(head-1);
|
||||
lex_row(buf, head);
|
||||
}
|
||||
}
|
||||
|
||||
void lex_row(std::vector<std::string> &v, unsigned &head){
|
||||
/* --- MUST COMPUTE --- */
|
||||
algo::do_eval(v[algo::OPR1], v[algo::OPERATOR][0], v[algo::OPR2]);
|
||||
/* --- */
|
||||
|
||||
/* --- INSTRUCTION BREANCHING --- */
|
||||
/* Is jump*/
|
||||
if(v[algo::JUMP][0] != algo::EMPTY_CELL){
|
||||
algo::jmp j;
|
||||
try{
|
||||
j = (algo::jmp)(stoi(v[algo::JUMP]));
|
||||
}catch(...){
|
||||
puts(RED "Non sensical jump condition." NORMAL);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(MAGENTA "Jump condition %s (%s) %s %s (%s) with %d. " NORMAL,
|
||||
v[algo::OPR1].c_str(),
|
||||
algo::deref(v[algo::OPR1]).c_str(),
|
||||
v[algo::OPERATOR].c_str(),
|
||||
algo::deref(v[algo::OPR2]).c_str(),
|
||||
v[algo::OPR2].c_str(),
|
||||
(int)j
|
||||
);
|
||||
#endif
|
||||
if(algo::jump(head, j, v[algo::DESTINATION], v[algo::ASSIGNMENT][0])){
|
||||
--head;
|
||||
#ifdef DEBUG
|
||||
puts(MAGENTA "Continueing." NORMAL);
|
||||
#endif
|
||||
}else{
|
||||
#ifdef DEBUG
|
||||
puts(MAGENTA "Falling through." NORMAL);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Is assignemt */
|
||||
if(v[algo::ASSIGNMENT][0] != algo::EMPTY_CELL){
|
||||
algo::assign(algo::arref(v[algo::DESTINATION]), algo::vars["eval"]);
|
||||
#ifdef DEBUG
|
||||
printf(CYAN "Assigned '%s' to '%s' (%s). (%s %s %s %c %s)\n" NORMAL,
|
||||
algo::vars["eval"].c_str(),
|
||||
v[algo::DESTINATION].c_str(),
|
||||
algo::arref(v[algo::DESTINATION]).c_str(),
|
||||
//
|
||||
v[algo::DESTINATION].c_str(),
|
||||
v[algo::ASSIGNMENT].c_str(),
|
||||
v[algo::OPR1].c_str(),
|
||||
v[algo::OPERATOR][0],
|
||||
v[algo::OPR2].c_str());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/* --- */
|
||||
}
|
8
Cati/src/lexer.h
Normal file
8
Cati/src/lexer.h
Normal file
@ -0,0 +1,8 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
void lex_file(const char* const f);
|
||||
void lex_row(std::vector<std::string> &v, unsigned &head);
|
||||
|
||||
extern unsigned long long instruction_counter;
|
68
Cati/src/main.cpp
Normal file
68
Cati/src/main.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
//#include "JokerTao.h"
|
||||
#include <unordered_map>
|
||||
//
|
||||
#include "algo.h"
|
||||
#include "lexer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
char* f;
|
||||
|
||||
[[ noreturn ]] void end(int ignore = 0){
|
||||
#ifdef DEBUG
|
||||
printf(NORMAL);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(GREEN "\" Standard variables\n" NORMAL);
|
||||
const char *const *c = algo::standard_vars-1;
|
||||
while((c++, *c != NULL)){
|
||||
printf("%s: %s\n", *c, algo::vars[*c].c_str());
|
||||
algo::vars.erase(*c);
|
||||
}
|
||||
|
||||
printf(GREEN "\" User variables\n" NORMAL);
|
||||
vector<char*> vpbuf;
|
||||
for(auto &&i : algo::vars){
|
||||
char *a;
|
||||
asprintf(&a, "%s: %s\n", i.first.c_str(), i.second.c_str());
|
||||
vpbuf.push_back(a);
|
||||
}
|
||||
std::sort(vpbuf.begin(), vpbuf.end(), [](char* a, char* b){ return (strcmp(a, b) < 1); });
|
||||
for(auto &&i : vpbuf){
|
||||
cout << i;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
bool init(){
|
||||
ios::sync_with_stdio(true);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
signal(SIGINT, end);
|
||||
|
||||
printf("[init] ");
|
||||
algo::init();
|
||||
puts("");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
signed main(int argc, char* argv[]){
|
||||
if(argc < 2){ return 0; }
|
||||
|
||||
init();
|
||||
|
||||
f = argv[1];
|
||||
lex_file(f);
|
||||
|
||||
end();
|
||||
}
|
1821
Cati/src/rapidcsv.h
Normal file
1821
Cati/src/rapidcsv.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user