From 94dcd4c50e6e5eb7e9719db8b6b5b79da77f322d Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 20 Mar 2023 17:57:47 +0100 Subject: [PATCH] Everywhere: Pass step1 tests by supporting more Tokens in the Reader --- src/ast.cpp | 6 +-- src/ast.h | 56 ++++++++++++++++---------- src/lexer.cpp | 4 +- src/printer.cpp | 26 +++++++++++- src/reader.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ src/reader.h | 17 +++++--- 6 files changed, 180 insertions(+), 33 deletions(-) diff --git a/src/ast.cpp b/src/ast.cpp index 5b14c23..61622d5 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -10,16 +10,14 @@ namespace blaze { -List::~List() +Collection::~Collection() { for (auto node : m_nodes) { delete node; } } -// ----------------------------------------- - -void List::addNode(ASTNode* node) +void Collection::addNode(ASTNode* node) { m_nodes.push_back(node); } diff --git a/src/ast.h b/src/ast.h index 5c411c7..66840cd 100644 --- a/src/ast.h +++ b/src/ast.h @@ -23,6 +23,7 @@ public: template bool fastIs() const = delete; + virtual bool isCollection() const { return false; } virtual bool isVector() const { return false; } virtual bool isHashMap() const { return false; } virtual bool isList() const { return false; } @@ -30,17 +31,25 @@ public: virtual bool isNumber() const { return false; } virtual bool isSpecialSymbol() const { return false; } virtual bool isSymbol() const { return false; } + +protected: + ASTNode() {} }; // ----------------------------------------- -// [] -class Vector final : public ASTNode { +class Collection : public ASTNode { public: - Vector(); - virtual ~Vector(); + virtual ~Collection() override; - virtual bool isVector() const override { return true; } + virtual bool isCollection() const override { return true; } + + void addNode(ASTNode* node); + + const std::vector& nodes() const { return m_nodes; } + +protected: + Collection() {} private: std::vector m_nodes; @@ -48,34 +57,38 @@ private: // ----------------------------------------- +// [] +class Vector final : public Collection { +public: + Vector() = default; + virtual ~Vector() = default; + + virtual bool isCollection() const override { return false; } + virtual bool isVector() const override { return true; } +}; + +// ----------------------------------------- + // {} -class HashMap final : public ASTNode { +class HashMap final : public Collection { public: - HashMap(); - virtual ~HashMap(); + HashMap() = default; + virtual ~HashMap() = default; + virtual bool isCollection() const override { return false; } virtual bool isHashMap() const override { return true; } - -private: - std::vector m_nodes; }; // ----------------------------------------- // () -class List final : public ASTNode { +class List final : public Collection { public: List() = default; - virtual ~List() override; + virtual ~List() = default; + virtual bool isCollection() const override { return false; } virtual bool isList() const override { return true; } - - void addNode(ASTNode* node); - - const std::vector& nodes() const { return m_nodes; } - -private: - std::vector m_nodes; }; // ----------------------------------------- @@ -143,6 +156,9 @@ private: // ----------------------------------------- // clang-format off +template<> +inline bool ASTNode::fastIs() const { return isCollection(); } + template<> inline bool ASTNode::fastIs() const { return isVector(); } diff --git a/src/lexer.cpp b/src/lexer.cpp index 4f4ffe8..5d15103 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -39,10 +39,10 @@ void Lexer::tokenize() consumeSpliceUnquoteOrUnquote(); break; case '[': - m_tokens.push_back({ Token::Type::ParenOpen, m_line, m_column, "[" }); + m_tokens.push_back({ Token::Type::BracketOpen, m_line, m_column, "[" }); break; case ']': - m_tokens.push_back({ Token::Type::ParenClose, m_line, m_column, "]" }); + m_tokens.push_back({ Token::Type::BracketClose, m_line, m_column, "]" }); break; case '{': m_tokens.push_back({ Token::Type::BraceOpen, m_line, m_column, "{" }); diff --git a/src/printer.cpp b/src/printer.cpp index 1b4688b..7f13104 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -48,7 +48,31 @@ void Printer::dumpImpl(ASTNode* node) } }; - if (is(node)) { + if (is(node)) { + printSpacing(); + print("["); + m_firstNode = false; + m_previousNodeIsList = true; + Vector* vector = static_cast(node); + for (size_t i = 0; i < vector->nodes().size(); ++i) { + dumpImpl(vector->nodes()[i]); + m_previousNodeIsList = false; + } + print("]"); + } + else if (is(node)) { + printSpacing(); + print("{{"); + m_firstNode = false; + m_previousNodeIsList = true; + HashMap* hash_map = static_cast(node); + for (size_t i = 0; i < hash_map->nodes().size(); ++i) { + dumpImpl(hash_map->nodes()[i]); + m_previousNodeIsList = false; + } + print("}}"); + } + else if (is(node)) { printSpacing(); print("("); m_firstNode = false; diff --git a/src/reader.cpp b/src/reader.cpp index fe34d31..f9c7bd8 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -59,6 +59,8 @@ void Reader::read() case Token::Type::Value: Error::the().addError("more than one sexp in input"); break; + case Token::Type::Comment: + break; default: Error::the().addError("unknown error"); break; @@ -76,6 +78,22 @@ ASTNode* Reader::readImpl() case Token::Type::Special: // ~@ return readSpliceUnquote(); break; + case Token::Type::BracketOpen: // [ + return readVector(); + break; + case Token::Type::BracketClose: // ] + m_invalid_syntax = true; + m_error_character = ']'; + return nullptr; + break; + case Token::Type::BraceOpen: // { + return readHashMap(); + break; + case Token::Type::BraceClose: // } + m_invalid_syntax = true; + m_error_character = '}'; + return nullptr; + break; case Token::Type::ParenOpen: // ( return readList(); break; @@ -93,9 +111,19 @@ ASTNode* Reader::readImpl() case Token::Type::Tilde: // ~ return readUnquote(); break; + case Token::Type::Caret: // ^ + return readWithMeta(); + break; + case Token::Type::At: // @ + return readDeref(); + break; case Token::Type::String: return readString(); break; + case Token::Type::Comment: // ; + ignore(); + return nullptr; + break; case Token::Type::Value: return readValue(); break; @@ -124,6 +152,40 @@ ASTNode* Reader::readSpliceUnquote() return list; } +ASTNode* Reader::readVector() +{ + ignore(); // [ + + Vector* vector = new Vector(); + while (!isEOF() && peek().type != Token::Type::BracketClose) { + vector->addNode(readImpl()); + } + + if (!consumeSpecific(Token { .type = Token::Type::BracketClose })) { // ] + m_error_character = ']'; + m_is_unbalanced = true; + } + + return vector; +} + +ASTNode* Reader::readHashMap() +{ + ignore(); // { + + HashMap* vector = new HashMap(); + while (!isEOF() && peek().type != Token::Type::BraceClose) { + vector->addNode(readImpl()); + } + + if (!consumeSpecific(Token { .type = Token::Type::BraceClose })) { // } + m_error_character = '}'; + m_is_unbalanced = true; + } + + return vector; +} + ASTNode* Reader::readList() { ignore(); // ( @@ -189,6 +251,43 @@ ASTNode* Reader::readUnquote() return list; } +ASTNode* Reader::readWithMeta() +{ + ignore(); // ^ + + ignore(); // first token + if (isEOF()) { // second token + Error::the().addError("expected form, got EOF"); + return nullptr; + } + retreat(); + + List* list = new List(); + list->addNode(new Symbol("with-meta")); + ASTNode* first = readImpl(); + ASTNode* second = readImpl(); + list->addNode(second); + list->addNode(first); + + return list; +} + +ASTNode* Reader::readDeref() +{ + ignore(); // @ + + if (isEOF()) { + Error::the().addError("expected form, got EOF"); + return nullptr; + } + + List* list = new List(); + list->addNode(new Symbol("deref")); + list->addNode(readImpl()); + + return list; +} + ASTNode* Reader::readString() { std::string symbol = consume().symbol; @@ -248,6 +347,11 @@ void Reader::ignore() m_index++; } +void Reader::retreat() +{ + m_index--; +} + // ----------------------------------------- void Reader::dump() diff --git a/src/reader.h b/src/reader.h index 99d93e7..d30b4a0 100644 --- a/src/reader.h +++ b/src/reader.h @@ -32,14 +32,19 @@ private: Token consume(); bool consumeSpecific(Token token); void ignore(); + void retreat(); ASTNode* readImpl(); - ASTNode* readSpliceUnquote(); - ASTNode* readList(); - ASTNode* readQuote(); - ASTNode* readQuasiQuote(); - ASTNode* readUnquote(); - ASTNode* readString(); + ASTNode* readSpliceUnquote(); // ~@ + ASTNode* readVector(); // [] + ASTNode* readHashMap(); // {} + ASTNode* readList(); // () + ASTNode* readQuote(); // ' + ASTNode* readQuasiQuote(); // ` + ASTNode* readUnquote(); // ~ + ASTNode* readWithMeta(); // ^ + ASTNode* readDeref(); // @ + ASTNode* readString(); // "foobar" ASTNode* readValue(); void dumpImpl(ASTNode* node);