Add enums
This commit is contained in:
parent
999db12a3a
commit
41c70bce44
@ -3,6 +3,7 @@
|
|||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace hex::lang {
|
namespace hex::lang {
|
||||||
@ -13,6 +14,7 @@ namespace hex::lang {
|
|||||||
VariableDecl,
|
VariableDecl,
|
||||||
TypeDecl,
|
TypeDecl,
|
||||||
Struct,
|
Struct,
|
||||||
|
Enum,
|
||||||
Scope,
|
Scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,4 +80,19 @@ namespace hex::lang {
|
|||||||
std::string m_name, m_customTypeName;
|
std::string m_name, m_customTypeName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ASTNodeEnum : public ASTNode {
|
||||||
|
public:
|
||||||
|
explicit ASTNodeEnum(const Token::TypeToken::Type &type, const std::string &name)
|
||||||
|
: ASTNode(Type::Enum), m_type(type), m_name(name) { }
|
||||||
|
|
||||||
|
const std::string& getName() const { return this->m_name; };
|
||||||
|
|
||||||
|
const Token::TypeToken::Type& getUnderlyingType() const { return this->m_type; }
|
||||||
|
std::vector<std::pair<u64, std::string>>& getValues() { return this->m_values; }
|
||||||
|
private:
|
||||||
|
Token::TypeToken::Type m_type;
|
||||||
|
std::string m_name;
|
||||||
|
std::vector<std::pair<u64, std::string>> m_values;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -25,7 +25,8 @@ namespace hex::lang {
|
|||||||
struct KeywordToken {
|
struct KeywordToken {
|
||||||
enum class Keyword {
|
enum class Keyword {
|
||||||
Struct,
|
Struct,
|
||||||
Using
|
Using,
|
||||||
|
Enum
|
||||||
} keyword;
|
} keyword;
|
||||||
} keywordToken;
|
} keywordToken;
|
||||||
struct IdentifierToken {
|
struct IdentifierToken {
|
||||||
@ -34,7 +35,8 @@ namespace hex::lang {
|
|||||||
struct OperatorToken {
|
struct OperatorToken {
|
||||||
enum class Operator {
|
enum class Operator {
|
||||||
AtDeclaration,
|
AtDeclaration,
|
||||||
Assignment
|
Assignment,
|
||||||
|
Inherit
|
||||||
} op;
|
} op;
|
||||||
} operatorToken;
|
} operatorToken;
|
||||||
struct IntegerToken {
|
struct IntegerToken {
|
||||||
|
@ -70,6 +70,7 @@ namespace hex::lang {
|
|||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
|
||||||
while (offset < code.length()) {
|
while (offset < code.length()) {
|
||||||
|
|
||||||
// Handle comments
|
// Handle comments
|
||||||
if (code[offset] == '/') {
|
if (code[offset] == '/') {
|
||||||
offset++;
|
offset++;
|
||||||
@ -121,6 +122,9 @@ namespace hex::lang {
|
|||||||
} else if (c == '=') {
|
} else if (c == '=') {
|
||||||
tokens.push_back({.type = Token::Type::Operator, .operatorToken = { .op = Token::OperatorToken::Operator::Assignment}});
|
tokens.push_back({.type = Token::Type::Operator, .operatorToken = { .op = Token::OperatorToken::Operator::Assignment}});
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
} else if (c == ':') {
|
||||||
|
tokens.push_back({.type = Token::Type::Operator, .operatorToken = { .op = Token::OperatorToken::Operator::Inherit}});
|
||||||
|
offset += 1;
|
||||||
} else if (std::isalpha(c)) {
|
} else if (std::isalpha(c)) {
|
||||||
std::string identifier = matchTillInvalid(&code[offset], [](char c) -> bool { return std::isalnum(c) || c == '_'; });
|
std::string identifier = matchTillInvalid(&code[offset], [](char c) -> bool { return std::isalnum(c) || c == '_'; });
|
||||||
|
|
||||||
@ -130,6 +134,8 @@ namespace hex::lang {
|
|||||||
tokens.push_back({.type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Struct}});
|
tokens.push_back({.type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Struct}});
|
||||||
else if (identifier == "using")
|
else if (identifier == "using")
|
||||||
tokens.push_back({.type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Using}});
|
tokens.push_back({.type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Using}});
|
||||||
|
else if (identifier == "enum")
|
||||||
|
tokens.push_back({.type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Enum}});
|
||||||
|
|
||||||
// Check for built-in types
|
// Check for built-in types
|
||||||
else if (identifier == "u8")
|
else if (identifier == "u8")
|
||||||
|
@ -51,7 +51,7 @@ namespace hex::lang {
|
|||||||
return new ASTNodeVariableDecl(Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer);
|
return new ASTNodeVariableDecl(Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ASTNode*> parseStruct(TokenIter &curr) {
|
ASTNode* parseStruct(TokenIter &curr) {
|
||||||
const std::string &structName = curr[-2].identifierToken.identifier;
|
const std::string &structName = curr[-2].identifierToken.identifier;
|
||||||
std::vector<ASTNode*> nodes;
|
std::vector<ASTNode*> nodes;
|
||||||
|
|
||||||
@ -69,12 +69,51 @@ namespace hex::lang {
|
|||||||
|
|
||||||
if (!tryConsume(curr, {Token::Type::EndOfExpression})) {
|
if (!tryConsume(curr, {Token::Type::EndOfExpression})) {
|
||||||
for(auto &node : nodes) delete node;
|
for(auto &node : nodes) delete node;
|
||||||
return { };
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ASTNodeStruct(structName, nodes);
|
return new ASTNodeStruct(structName, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTNode* parseEnum(TokenIter &curr) {
|
||||||
|
const std::string &enumName = curr[-4].identifierToken.identifier;
|
||||||
|
const Token::TypeToken::Type underlyingType = curr[-2].typeToken.type;
|
||||||
|
|
||||||
|
if (curr[-3].operatorToken.op != Token::OperatorToken::Operator::Inherit)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ((static_cast<u32>(underlyingType) & 0x0F) != 0x00)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto enumNode = new ASTNodeEnum(underlyingType, enumName);
|
||||||
|
|
||||||
|
while (!tryConsume(curr, {Token::Type::ScopeClose})) {
|
||||||
|
if (tryConsume(curr, { Token::Type::Identifier, Token::Type::Separator})) {
|
||||||
|
u64 value;
|
||||||
|
if (enumNode->getValues().empty())
|
||||||
|
value = 0;
|
||||||
|
else
|
||||||
|
value = enumNode->getValues().back().first + 1;
|
||||||
|
|
||||||
|
enumNode->getValues().push_back({ value, curr[-2].identifierToken.identifier });
|
||||||
|
}
|
||||||
|
else if (tryConsume(curr, { Token::Type::Identifier, Token::Type::Operator, Token::Type::Integer, Token::Type::Separator})) {
|
||||||
|
enumNode->getValues().push_back({ curr[-2].integerToken.integer, curr[-4].identifierToken.identifier });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delete enumNode;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tryConsume(curr, {Token::Type::EndOfExpression})) {
|
||||||
|
delete enumNode;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumNode;
|
||||||
|
}
|
||||||
|
|
||||||
ASTNode *parseScope(TokenIter &curr) {
|
ASTNode *parseScope(TokenIter &curr) {
|
||||||
return new ASTNodeScope(parseTillToken(curr, Token::Type::ScopeClose));
|
return new ASTNodeScope(parseTillToken(curr, Token::Type::ScopeClose));
|
||||||
}
|
}
|
||||||
@ -111,12 +150,27 @@ namespace hex::lang {
|
|||||||
if (curr[-3].keywordToken.keyword == Token::KeywordToken::Keyword::Struct) {
|
if (curr[-3].keywordToken.keyword == Token::KeywordToken::Keyword::Struct) {
|
||||||
auto structAst = parseStruct(curr);
|
auto structAst = parseStruct(curr);
|
||||||
|
|
||||||
if (!structAst.has_value()) {
|
if (structAst == nullptr) {
|
||||||
for(auto &node : program) delete node;
|
for(auto &node : program) delete node;
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
program.push_back(structAst.value());
|
program.push_back(structAst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
|
||||||
|
} // Enum
|
||||||
|
if (tryConsume(curr, { Token::Type::Keyword, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::ScopeOpen })) {
|
||||||
|
if (curr[-5].keywordToken.keyword == Token::KeywordToken::Keyword::Enum) {
|
||||||
|
auto enumAst = parseEnum(curr);
|
||||||
|
|
||||||
|
if (enumAst == nullptr) {
|
||||||
|
for(auto &node : program) delete node;
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
|
program.push_back(enumAst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user