Everywhere: Pass step1 tests by supporting more Tokens in the Reader
This commit is contained in:
+2
-4
@@ -10,16 +10,14 @@
|
|||||||
|
|
||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
List::~List()
|
Collection::~Collection()
|
||||||
{
|
{
|
||||||
for (auto node : m_nodes) {
|
for (auto node : m_nodes) {
|
||||||
delete node;
|
delete node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
void Collection::addNode(ASTNode* node)
|
||||||
|
|
||||||
void List::addNode(ASTNode* node)
|
|
||||||
{
|
{
|
||||||
m_nodes.push_back(node);
|
m_nodes.push_back(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
bool fastIs() const = delete;
|
bool fastIs() const = delete;
|
||||||
|
|
||||||
|
virtual bool isCollection() const { return false; }
|
||||||
virtual bool isVector() const { return false; }
|
virtual bool isVector() const { return false; }
|
||||||
virtual bool isHashMap() const { return false; }
|
virtual bool isHashMap() const { return false; }
|
||||||
virtual bool isList() const { return false; }
|
virtual bool isList() const { return false; }
|
||||||
@@ -30,56 +31,68 @@ public:
|
|||||||
virtual bool isNumber() const { return false; }
|
virtual bool isNumber() const { return false; }
|
||||||
virtual bool isSpecialSymbol() const { return false; }
|
virtual bool isSpecialSymbol() const { return false; }
|
||||||
virtual bool isSymbol() const { return false; }
|
virtual bool isSymbol() const { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ASTNode() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// []
|
class Collection : public ASTNode {
|
||||||
class Vector final : public ASTNode {
|
|
||||||
public:
|
public:
|
||||||
Vector();
|
virtual ~Collection() override;
|
||||||
virtual ~Vector();
|
|
||||||
|
|
||||||
virtual bool isVector() const override { return true; }
|
virtual bool isCollection() const override { return true; }
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<ASTNode*> m_nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
// {}
|
|
||||||
class HashMap final : public ASTNode {
|
|
||||||
public:
|
|
||||||
HashMap();
|
|
||||||
virtual ~HashMap();
|
|
||||||
|
|
||||||
virtual bool isHashMap() const override { return true; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<ASTNode*> m_nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
// ()
|
|
||||||
class List final : public ASTNode {
|
|
||||||
public:
|
|
||||||
List() = default;
|
|
||||||
virtual ~List() override;
|
|
||||||
|
|
||||||
virtual bool isList() const override { return true; }
|
|
||||||
|
|
||||||
void addNode(ASTNode* node);
|
void addNode(ASTNode* node);
|
||||||
|
|
||||||
const std::vector<ASTNode*>& nodes() const { return m_nodes; }
|
const std::vector<ASTNode*>& nodes() const { return m_nodes; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Collection() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ASTNode*> m_nodes;
|
std::vector<ASTNode*> m_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
|
// []
|
||||||
|
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 Collection {
|
||||||
|
public:
|
||||||
|
HashMap() = default;
|
||||||
|
virtual ~HashMap() = default;
|
||||||
|
|
||||||
|
virtual bool isCollection() const override { return false; }
|
||||||
|
virtual bool isHashMap() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
// ()
|
||||||
|
class List final : public Collection {
|
||||||
|
public:
|
||||||
|
List() = default;
|
||||||
|
virtual ~List() = default;
|
||||||
|
|
||||||
|
virtual bool isCollection() const override { return false; }
|
||||||
|
virtual bool isList() const override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
// "string"
|
// "string"
|
||||||
class String final : public ASTNode {
|
class String final : public ASTNode {
|
||||||
public:
|
public:
|
||||||
@@ -143,6 +156,9 @@ private:
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
template<>
|
||||||
|
inline bool ASTNode::fastIs<Collection>() const { return isCollection(); }
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool ASTNode::fastIs<Vector>() const { return isVector(); }
|
inline bool ASTNode::fastIs<Vector>() const { return isVector(); }
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -39,10 +39,10 @@ void Lexer::tokenize()
|
|||||||
consumeSpliceUnquoteOrUnquote();
|
consumeSpliceUnquoteOrUnquote();
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
m_tokens.push_back({ Token::Type::ParenOpen, m_line, m_column, "[" });
|
m_tokens.push_back({ Token::Type::BracketOpen, m_line, m_column, "[" });
|
||||||
break;
|
break;
|
||||||
case ']':
|
case ']':
|
||||||
m_tokens.push_back({ Token::Type::ParenClose, m_line, m_column, "]" });
|
m_tokens.push_back({ Token::Type::BracketClose, m_line, m_column, "]" });
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
m_tokens.push_back({ Token::Type::BraceOpen, m_line, m_column, "{" });
|
m_tokens.push_back({ Token::Type::BraceOpen, m_line, m_column, "{" });
|
||||||
|
|||||||
+25
-1
@@ -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();
|
printSpacing();
|
||||||
print("(");
|
print("(");
|
||||||
m_firstNode = false;
|
m_firstNode = false;
|
||||||
|
|||||||
+104
@@ -59,6 +59,8 @@ void Reader::read()
|
|||||||
case Token::Type::Value:
|
case Token::Type::Value:
|
||||||
Error::the().addError("more than one sexp in input");
|
Error::the().addError("more than one sexp in input");
|
||||||
break;
|
break;
|
||||||
|
case Token::Type::Comment:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Error::the().addError("unknown error");
|
Error::the().addError("unknown error");
|
||||||
break;
|
break;
|
||||||
@@ -76,6 +78,22 @@ ASTNode* Reader::readImpl()
|
|||||||
case Token::Type::Special: // ~@
|
case Token::Type::Special: // ~@
|
||||||
return readSpliceUnquote();
|
return readSpliceUnquote();
|
||||||
break;
|
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: // (
|
case Token::Type::ParenOpen: // (
|
||||||
return readList();
|
return readList();
|
||||||
break;
|
break;
|
||||||
@@ -93,9 +111,19 @@ ASTNode* Reader::readImpl()
|
|||||||
case Token::Type::Tilde: // ~
|
case Token::Type::Tilde: // ~
|
||||||
return readUnquote();
|
return readUnquote();
|
||||||
break;
|
break;
|
||||||
|
case Token::Type::Caret: // ^
|
||||||
|
return readWithMeta();
|
||||||
|
break;
|
||||||
|
case Token::Type::At: // @
|
||||||
|
return readDeref();
|
||||||
|
break;
|
||||||
case Token::Type::String:
|
case Token::Type::String:
|
||||||
return readString();
|
return readString();
|
||||||
break;
|
break;
|
||||||
|
case Token::Type::Comment: // ;
|
||||||
|
ignore();
|
||||||
|
return nullptr;
|
||||||
|
break;
|
||||||
case Token::Type::Value:
|
case Token::Type::Value:
|
||||||
return readValue();
|
return readValue();
|
||||||
break;
|
break;
|
||||||
@@ -124,6 +152,40 @@ ASTNode* Reader::readSpliceUnquote()
|
|||||||
return list;
|
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()
|
ASTNode* Reader::readList()
|
||||||
{
|
{
|
||||||
ignore(); // (
|
ignore(); // (
|
||||||
@@ -189,6 +251,43 @@ ASTNode* Reader::readUnquote()
|
|||||||
return list;
|
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()
|
ASTNode* Reader::readString()
|
||||||
{
|
{
|
||||||
std::string symbol = consume().symbol;
|
std::string symbol = consume().symbol;
|
||||||
@@ -248,6 +347,11 @@ void Reader::ignore()
|
|||||||
m_index++;
|
m_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Reader::retreat()
|
||||||
|
{
|
||||||
|
m_index--;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void Reader::dump()
|
void Reader::dump()
|
||||||
|
|||||||
+11
-6
@@ -32,14 +32,19 @@ private:
|
|||||||
Token consume();
|
Token consume();
|
||||||
bool consumeSpecific(Token token);
|
bool consumeSpecific(Token token);
|
||||||
void ignore();
|
void ignore();
|
||||||
|
void retreat();
|
||||||
|
|
||||||
ASTNode* readImpl();
|
ASTNode* readImpl();
|
||||||
ASTNode* readSpliceUnquote();
|
ASTNode* readSpliceUnquote(); // ~@
|
||||||
ASTNode* readList();
|
ASTNode* readVector(); // []
|
||||||
ASTNode* readQuote();
|
ASTNode* readHashMap(); // {}
|
||||||
ASTNode* readQuasiQuote();
|
ASTNode* readList(); // ()
|
||||||
ASTNode* readUnquote();
|
ASTNode* readQuote(); // '
|
||||||
ASTNode* readString();
|
ASTNode* readQuasiQuote(); // `
|
||||||
|
ASTNode* readUnquote(); // ~
|
||||||
|
ASTNode* readWithMeta(); // ^
|
||||||
|
ASTNode* readDeref(); // @
|
||||||
|
ASTNode* readString(); // "foobar"
|
||||||
ASTNode* readValue();
|
ASTNode* readValue();
|
||||||
|
|
||||||
void dumpImpl(ASTNode* node);
|
void dumpImpl(ASTNode* node);
|
||||||
|
|||||||
Reference in New Issue
Block a user