Add a very basic List implementation
This commit is contained in:
parent
cbea0c8e28
commit
576eba6451
|
@ -23,7 +23,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
# Let's ensure -std=c++xx instead of -std=g++xx
|
# Let's ensure -std=c++xx instead of -std=g++xx
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG
|
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
|
set(CMAKE_LINKER_FLAGS_DEBUG
|
||||||
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
|
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,15 @@ int main(int argc, char *argv[]) {
|
||||||
char *input_file = argv[1];
|
char *input_file = argv[1];
|
||||||
Reader *r = new Reader(input_file);
|
Reader *r = new Reader(input_file);
|
||||||
ast_tree &ast = r->read();
|
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;
|
delete r;
|
||||||
cout << "\nEND<<" << endl;
|
cout << "\nEND<<" << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
4
builder
4
builder
|
@ -78,7 +78,9 @@ case "$command" in
|
||||||
compile
|
compile
|
||||||
;;
|
;;
|
||||||
"run")
|
"run")
|
||||||
run "$@"
|
echo "##############"
|
||||||
|
echo "${@:2}"
|
||||||
|
run "${@:2}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
"scan-build")
|
"scan-build")
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace serene {
|
||||||
class AExpr {
|
class AExpr {
|
||||||
public:
|
public:
|
||||||
virtual std::string string_repr() = 0;
|
virtual std::string string_repr() = 0;
|
||||||
virtual ~AExpr() = default;
|
virtual ~AExpr() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<AExpr> ast_node;
|
typedef std::unique_ptr<AExpr> ast_node;
|
||||||
|
|
|
@ -31,29 +31,36 @@
|
||||||
|
|
||||||
namespace serene {
|
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 {
|
class List: public AExpr {
|
||||||
public:
|
public:
|
||||||
ast_node first;
|
std::unique_ptr<ListNode> head;
|
||||||
std::unique_ptr<List> rest;
|
std::unique_ptr<ListNode> tail;
|
||||||
std::size_t len;
|
std::size_t len;
|
||||||
|
|
||||||
List(): first(nullptr), rest(nullptr), len(0) {};
|
List(): head{nullptr}, tail{nullptr}, len{0} {};
|
||||||
List(ast_node f, std::unique_ptr<List> r): first(std::move(f)),
|
List(const List &list);
|
||||||
rest(std::move(r)),
|
List(List &&list);
|
||||||
len(r ? r->length() + 1 : 0)
|
|
||||||
{};
|
|
||||||
|
|
||||||
List(ast_tree list);
|
|
||||||
|
|
||||||
std::string string_repr();
|
std::string string_repr();
|
||||||
std::size_t length();
|
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;
|
typedef std::unique_ptr<List> ast_list_node;
|
||||||
|
|
|
@ -58,18 +58,20 @@ namespace serene {
|
||||||
|
|
||||||
char get_char(const bool skip_whitespace);
|
char get_char(const bool skip_whitespace);
|
||||||
void unget_char();
|
void unget_char();
|
||||||
int is_valid_for_identifier(char c);
|
bool is_valid_for_identifier(char c);
|
||||||
|
|
||||||
// The property to store the ast tree
|
// The property to store the ast tree
|
||||||
ast_tree ast;
|
ast_tree ast;
|
||||||
|
|
||||||
ast_node read_symbol();
|
ast_node read_symbol();
|
||||||
ast_list_node read_list();
|
ast_list_node read_list(List list);
|
||||||
ast_node read_expr();
|
ast_node read_expr();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reader(const std::string &input);
|
Reader(const std::string &input);
|
||||||
ast_tree &read();
|
ast_tree &read();
|
||||||
|
|
||||||
|
~Reader();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@ namespace serene {
|
||||||
public:
|
public:
|
||||||
Symbol(const std::string &name): name(name) {};
|
Symbol(const std::string &name): name(name) {};
|
||||||
std::string string_repr();
|
std::string string_repr();
|
||||||
~Symbol();
|
virtual ~Symbol();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
src/list.cpp
82
src/list.cpp
|
@ -31,33 +31,87 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace serene {
|
namespace serene {
|
||||||
ast_list_node List::to_list(ast_tree lst) {
|
void List::cons(ast_node f) {
|
||||||
auto l = make_unique<List>();
|
auto temp{std::make_unique<ListNode>(move(f))};
|
||||||
|
if(head) {
|
||||||
// Using a for loop with iterator
|
temp->next = move(head);
|
||||||
for(auto node = rbegin(lst); node != rend(lst); ++node) {
|
head->prev = move(temp);
|
||||||
l = l->cons(move(*node));
|
head = move(temp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
head = move(temp);
|
||||||
|
}
|
||||||
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return l;
|
List::List(const List &list) {
|
||||||
|
ListNode *root = list.head.get();
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_list_node List::cons(ast_node f) {
|
root = root->next.get();
|
||||||
|
|
||||||
return make_unique<List>(move(f), unique_ptr<List>(move(*this)));
|
}
|
||||||
|
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() {
|
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() {
|
size_t List::length() {
|
||||||
if (this->len) {
|
return len;
|
||||||
return this->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
void List::cleanup() {
|
||||||
|
while(head) {
|
||||||
|
head = move(head->next);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
List::~List() {};
|
List::~List() {
|
||||||
|
fmt::print("asdsadadsddddddddddddddddddddddddd\n");
|
||||||
|
cleanup();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ namespace serene {
|
||||||
input_stream.write(input.c_str(), input.size());
|
input_stream.write(input.c_str(), input.size());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reader::~Reader() {
|
||||||
|
fmt::print("DELETE reader");
|
||||||
|
}
|
||||||
|
|
||||||
char Reader::get_char(const bool skip_whitespace) {
|
char Reader::get_char(const bool skip_whitespace) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
char c = input_stream.get();
|
char c = input_stream.get();
|
||||||
|
@ -52,7 +56,7 @@ namespace serene {
|
||||||
input_stream.unget();
|
input_stream.unget();
|
||||||
};
|
};
|
||||||
|
|
||||||
int Reader::is_valid_for_identifier(char c) {
|
bool Reader::is_valid_for_identifier(char c) {
|
||||||
READER_LOG("IS: {}\n", c);
|
READER_LOG("IS: {}\n", c);
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '!'
|
case '!'
|
||||||
|
@ -73,18 +77,15 @@ namespace serene {
|
||||||
| '@'
|
| '@'
|
||||||
| '^'
|
| '^'
|
||||||
| '_':
|
| '_':
|
||||||
READER_LOG("#######\n");
|
return true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((c >= 'a' && c <='z') ||
|
if((c >= 'a' && c <='z') ||
|
||||||
(c >= 'A' && c <= 'Z') ||
|
(c >= 'A' && c <= 'Z') ||
|
||||||
(c >= '0' && c <= '9')) {
|
(c >= '0' && c <= '9')) {
|
||||||
READER_LOG("#######@@@@2\n");
|
return true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
READER_LOG("#####111111111111112\n");
|
return false;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_node Reader::read_symbol() {
|
ast_node Reader::read_symbol() {
|
||||||
|
@ -93,39 +94,36 @@ namespace serene {
|
||||||
|
|
||||||
READER_LOG("Read symbol\n");
|
READER_LOG("Read symbol\n");
|
||||||
if(!this->is_valid_for_identifier(c)) {
|
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("");
|
string sym("");
|
||||||
|
|
||||||
while(c != EOF && (!(isspace(c)) && this->is_valid_for_identifier(c))) {
|
while(c != EOF && ((!(isspace(c)) && this->is_valid_for_identifier(c)))) {
|
||||||
READER_LOG("ABC: {}\n", c);
|
|
||||||
sym += c;
|
sym += c;
|
||||||
c = get_char(false);
|
c = get_char(false);
|
||||||
empty = false;
|
empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
READER_LOG("44444444444444\n");
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
READER_LOG("<<<<\n");
|
|
||||||
unget_char();
|
unget_char();
|
||||||
return make_unique<Symbol>(sym);
|
return make_unique<Symbol>(sym);
|
||||||
}
|
}
|
||||||
READER_LOG(">>>>>>>>>>>>\n");
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
ast_list_node Reader::read_list() {
|
ast_list_node Reader::read_list(List list) {
|
||||||
char c = get_char(true);
|
char c = get_char(true);
|
||||||
assert(c == '(');
|
assert(c == '(');
|
||||||
|
|
||||||
bool list_terminated = false;
|
bool list_terminated = false;
|
||||||
ast_tree lst;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
char c = get_char(true);
|
char c = get_char(true);
|
||||||
unget_char();
|
|
||||||
|
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case EOF:
|
case EOF:
|
||||||
|
@ -135,11 +133,14 @@ namespace serene {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lst.push_back(read_expr());
|
unget_char();
|
||||||
|
auto tmp{read_expr()};
|
||||||
|
list.add_tail(move(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
} while(!list_terminated);
|
} while(!list_terminated);
|
||||||
|
|
||||||
return List::to_list(move(lst));
|
return unique_ptr<List>(&list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,7 +152,7 @@ namespace serene {
|
||||||
|
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '(':
|
case '(':
|
||||||
return read_list();
|
return read_list(List());
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -166,10 +167,16 @@ namespace serene {
|
||||||
|
|
||||||
while(c != EOF) {
|
while(c != EOF) {
|
||||||
unget_char();
|
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);
|
c = get_char(true);
|
||||||
|
READER_LOG("11111 {}\n", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READER_LOG("333333333333333\n");
|
||||||
return this->ast;
|
return this->ast;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,7 @@ namespace serene {
|
||||||
return fmt::format("<Symbol: '{}'>", name);
|
return fmt::format("<Symbol: '{}'>", name);
|
||||||
};
|
};
|
||||||
|
|
||||||
Symbol::~Symbol() {};
|
Symbol::~Symbol() {
|
||||||
|
fmt::print("symbol dest\n");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue