Add a very basic List implementation

This commit is contained in:
Sameer Rahmani 2020-07-21 22:23:11 +01:00
parent cbea0c8e28
commit 576eba6451
10 changed files with 138 additions and 59 deletions

View File

@ -23,7 +23,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
"${CMAKE_CXX_FLAGS_DEBUG} -g -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

View File

@ -36,11 +36,15 @@ int main(int argc, char *argv[]) {
char *input_file = argv[1];
Reader *r = new Reader(input_file);
ast_tree &ast = r->read();
cout << "Size: " << ast.size() << endl;
for(const ast_node& x : ast) {
cout << x->string_repr() << " >> ";
}
cout << ast.at(2)->string_repr() << endl;
// for(const ast_node& x : ast) {
// cout << x->string_repr() << " >> ";
// }
delete r;
cout << "\nEND<<" << endl;
return 0;

View File

@ -78,7 +78,9 @@ case "$command" in
compile
;;
"run")
run "$@"
echo "##############"
echo "${@:2}"
run "${@:2}"
;;
"scan-build")

View File

@ -32,7 +32,7 @@ namespace serene {
class AExpr {
public:
virtual std::string string_repr() = 0;
virtual ~AExpr() = default;
virtual ~AExpr() {};
};
typedef std::unique_ptr<AExpr> ast_node;

View File

@ -31,29 +31,36 @@
namespace serene {
class ListNode {
public:
ast_node data;
std::unique_ptr<ListNode> next;
std::unique_ptr<ListNode> prev;
ListNode(ast_node node_data) : data{move(node_data)},
next{nullptr},
prev{nullptr} {};
};
class List: public AExpr {
public:
ast_node first;
std::unique_ptr<List> rest;
std::unique_ptr<ListNode> head;
std::unique_ptr<ListNode> tail;
std::size_t len;
List(): first(nullptr), rest(nullptr), len(0) {};
List(ast_node f, std::unique_ptr<List> r): first(std::move(f)),
rest(std::move(r)),
len(r ? r->length() + 1 : 0)
{};
List(): head{nullptr}, tail{nullptr}, len{0} {};
List(const List &list);
List(List &&list);
List(ast_tree list);
std::string string_repr();
std::size_t length();
std::unique_ptr<List> cons(ast_node f);
static std::unique_ptr<List> to_list(ast_tree lst);
void cons(ast_node f);
void add_tail(ast_node t);
void cleanup();
virtual ~List();
~List();
};
typedef std::unique_ptr<List> ast_list_node;

View File

@ -58,18 +58,20 @@ namespace serene {
char get_char(const bool skip_whitespace);
void unget_char();
int is_valid_for_identifier(char c);
bool is_valid_for_identifier(char c);
// The property to store the ast tree
ast_tree ast;
ast_node read_symbol();
ast_list_node read_list();
ast_list_node read_list(List list);
ast_node read_expr();
public:
Reader(const std::string &input);
ast_tree &read();
~Reader();
};
}

View File

@ -37,7 +37,8 @@ namespace serene {
public:
Symbol(const std::string &name): name(name) {};
std::string string_repr();
~Symbol();
virtual ~Symbol();
};
}

View File

@ -31,33 +31,87 @@
using namespace std;
namespace serene {
ast_list_node List::to_list(ast_tree lst) {
auto l = make_unique<List>();
// Using a for loop with iterator
for(auto node = rbegin(lst); node != rend(lst); ++node) {
l = l->cons(move(*node));
void List::cons(ast_node f) {
auto temp{std::make_unique<ListNode>(move(f))};
if(head) {
temp->next = move(head);
head->prev = move(temp);
head = move(temp);
}
return l;
else {
head = move(temp);
}
len++;
}
ast_list_node List::cons(ast_node f) {
List::List(const List &list) {
ListNode *root = list.head.get();
return make_unique<List>(move(f), unique_ptr<List>(move(*this)));
unique_ptr<ListNode> new_head{nullptr};
ListNode *pnew_head{nullptr};
while(root) {
auto temp{std::make_unique<ListNode>(unique_ptr<AExpr>(root->data.get()))};
if(new_head == nullptr) {
new_head = move(temp);
pnew_head = new_head.get();
} else {
pnew_head->next = move(temp);
pnew_head = pnew_head->next.get();
}
root = root->next.get();
}
head = move(new_head);
};
List::List(List &&list) {
head = move(list.head);
}
void List::add_tail(ast_node t) {
auto temp{std::make_unique<ListNode>(move(t))};
if(tail) {
temp->prev = move(tail);
tail->next = move(temp);
tail = move(temp);
len++;
}
else {
if (head) {
head->next = move(temp);
len++;
}
else {
cons(move(t));
}
}
}
string List::string_repr() {
return fmt::format("<List: '{}'>", first->string_repr());
if (head && head->data) {
return fmt::format("<List: '{}'>", head->data->string_repr());
}
else {
return "<List: empty>";
}
};
size_t List::length() {
if (this->len) {
return this->len;
}
return 0;
return len;
}
List::~List() {};
void List::cleanup() {
while(head) {
head = move(head->next);
}
};
List::~List() {
fmt::print("asdsadadsddddddddddddddddddddddddd\n");
cleanup();
};
}

View File

@ -37,6 +37,10 @@ namespace serene {
input_stream.write(input.c_str(), input.size());
};
Reader::~Reader() {
fmt::print("DELETE reader");
}
char Reader::get_char(const bool skip_whitespace) {
for(;;) {
char c = input_stream.get();
@ -52,7 +56,7 @@ namespace serene {
input_stream.unget();
};
int Reader::is_valid_for_identifier(char c) {
bool Reader::is_valid_for_identifier(char c) {
READER_LOG("IS: {}\n", c);
switch(c) {
case '!'
@ -73,18 +77,15 @@ namespace serene {
| '@'
| '^'
| '_':
READER_LOG("#######\n");
return 1;
return true;
}
if((c >= 'a' && c <='z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9')) {
READER_LOG("#######@@@@2\n");
return 1;
return true;
}
READER_LOG("#####111111111111112\n");
return 0;
return false;
}
ast_node Reader::read_symbol() {
@ -93,39 +94,36 @@ namespace serene {
READER_LOG("Read symbol\n");
if(!this->is_valid_for_identifier(c)) {
// TODO: Fix this when we implement the error handling
throw ReadError((char *)"Invalid character at the start of a symbol");
// TODO: Replece this with a tranceback function or something to raise
// synatx error.
fmt::print("Invalid character at the start of a symbol: '{}'\n", c);
exit(1);
}
string sym("");
while(c != EOF && (!(isspace(c)) && this->is_valid_for_identifier(c))) {
READER_LOG("ABC: {}\n", c);
while(c != EOF && ((!(isspace(c)) && this->is_valid_for_identifier(c)))) {
sym += c;
c = get_char(false);
empty = false;
}
READER_LOG("44444444444444\n");
if (!empty) {
READER_LOG("<<<<\n");
unget_char();
return make_unique<Symbol>(sym);
}
READER_LOG(">>>>>>>>>>>>\n");
return nullptr;
};
ast_list_node Reader::read_list() {
ast_list_node Reader::read_list(List list) {
char c = get_char(true);
assert(c == '(');
bool list_terminated = false;
ast_tree lst;
do {
char c = get_char(true);
unget_char();
switch(c) {
case EOF:
@ -135,11 +133,14 @@ namespace serene {
break;
default:
lst.push_back(read_expr());
unget_char();
auto tmp{read_expr()};
list.add_tail(move(tmp));
}
} while(!list_terminated);
return List::to_list(move(lst));
return unique_ptr<List>(&list);
}
@ -151,7 +152,7 @@ namespace serene {
switch(c) {
case '(':
return read_list();
return read_list(List());
case EOF:
return nullptr;
@ -166,10 +167,16 @@ namespace serene {
while(c != EOF) {
unget_char();
this->ast.push_back(read_expr());
auto tmp{read_expr()};
fmt::print("##### {}", tmp->string_repr());
if(tmp) {
this->ast.push_back(move(tmp));
}
c = get_char(true);
READER_LOG("11111 {}\n", c);
}
READER_LOG("333333333333333\n");
return this->ast;
};
}

View File

@ -35,5 +35,7 @@ namespace serene {
return fmt::format("<Symbol: '{}'>", name);
};
Symbol::~Symbol() {};
Symbol::~Symbol() {
fmt::print("symbol dest\n");
};
}