Browse Source

Everywhere: Pass step1 tests by supporting more Tokens in the Reader

master
Riyyi 2 years ago
parent
commit
94dcd4c50e
  1. 6
      src/ast.cpp
  2. 56
      src/ast.h
  3. 4
      src/lexer.cpp
  4. 26
      src/printer.cpp
  5. 104
      src/reader.cpp
  6. 17
      src/reader.h

6
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);
}

56
src/ast.h

@ -23,6 +23,7 @@ public:
template<typename T>
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<ASTNode*>& nodes() const { return m_nodes; }
protected:
Collection() {}
private:
std::vector<ASTNode*> 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<ASTNode*> 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<ASTNode*>& nodes() const { return m_nodes; }
private:
std::vector<ASTNode*> m_nodes;
};
// -----------------------------------------
@ -143,6 +156,9 @@ private:
// -----------------------------------------
// clang-format off
template<>
inline bool ASTNode::fastIs<Collection>() const { return isCollection(); }
template<>
inline bool ASTNode::fastIs<Vector>() const { return isVector(); }

4
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, "{" });

26
src/printer.cpp

@ -48,7 +48,31 @@ void Printer::dumpImpl(ASTNode* node)
}
};
if (is<List>(node)) {
if (is<Vector>(node)) {
printSpacing();
print("[");
m_firstNode = false;
m_previousNodeIsList = true;
Vector* vector = static_cast<Vector*>(node);
for (size_t i = 0; i < vector->nodes().size(); ++i) {
dumpImpl(vector->nodes()[i]);
m_previousNodeIsList = false;
}
print("]");
}
else if (is<HashMap>(node)) {
printSpacing();
print("{{");
m_firstNode = false;
m_previousNodeIsList = true;
HashMap* hash_map = static_cast<HashMap*>(node);
for (size_t i = 0; i < hash_map->nodes().size(); ++i) {
dumpImpl(hash_map->nodes()[i]);
m_previousNodeIsList = false;
}
print("}}");
}
else if (is<List>(node)) {
printSpacing();
print("(");
m_firstNode = false;

104
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()

17
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);

Loading…
Cancel
Save