patterns: Fixed recursive types

This commit is contained in:
WerWolv
2021-09-25 22:03:55 +02:00
parent ba97573f93
commit 9b4cf917d9
3 changed files with 37 additions and 34 deletions

View File

@@ -346,17 +346,10 @@ namespace hex::pl {
ASTNodeTypeDecl(const ASTNodeTypeDecl& other) : ASTNode(other), Attributable(other) {
this->m_name = other.m_name;
if (other.m_type != nullptr)
this->m_type = other.m_type->clone();
else
this->m_type = nullptr;
this->m_type = other.m_type;
this->m_endian = other.m_endian;
}
~ASTNodeTypeDecl() override {
delete this->m_type;
}
[[nodiscard]] ASTNode* clone() const override {
return new ASTNodeTypeDecl(*this);
}

View File

@@ -117,6 +117,8 @@ namespace hex::pl {
std::vector<ASTNode*> parseNamespace();
std::vector<ASTNode*> parseStatements();
ASTNodeTypeDecl* addType(const std::string &name, ASTNode *node, std::optional<std::endian> endian = std::nullopt);
std::vector<ASTNode*> parseTillToken(Token::Type endTokenType, const auto value) {
std::vector<ASTNode*> program;
auto guard = SCOPE_GUARD {

View File

@@ -684,7 +684,7 @@ namespace hex::pl {
auto *type = dynamic_cast<ASTNodeTypeDecl *>(parseType());
if (type == nullptr) throwParseError("invalid type used in variable declaration", -1);
return create(new ASTNodeTypeDecl(name, type, type->getEndian()));
return addType(name, type, type->getEndian());
}
// padding[(parseMathematicalExpression)]
@@ -707,14 +707,14 @@ namespace hex::pl {
auto variableCleanup = SCOPE_GUARD { for (auto var : variables) delete var; };
do {
variables.push_back(create(new ASTNodeVariableDecl(getValue<Token::Identifier>(-1).get(), type->clone())));
variables.push_back(create(new ASTNodeVariableDecl(getValue<Token::Identifier>(-1).get(), type)));
} while (MATCHES(sequence(SEPARATOR_COMMA, IDENTIFIER)));
variableCleanup.release();
return create(new ASTNodeMultiVariableDecl(variables));
} else
return create(new ASTNodeVariableDecl(getValue<Token::Identifier>(-1).get(), type->clone()));
return create(new ASTNodeVariableDecl(getValue<Token::Identifier>(-1).get(), type));
}
// (parseType) Identifier[(parseMathematicalExpression)]
@@ -736,7 +736,7 @@ namespace hex::pl {
sizeCleanup.release();
return create(new ASTNodeArrayVariableDecl(name, type->clone(), size));
return create(new ASTNodeArrayVariableDecl(name, type, size));
}
// (parseType) *Identifier : (parseType)
@@ -752,7 +752,7 @@ namespace hex::pl {
throwParseError("invalid type used for pointer size", -1);
}
return create(new ASTNodePointerVariableDecl(name, type->clone(), sizeType));
return create(new ASTNodePointerVariableDecl(name, type, sizeType));
}
// [(parsePadding)|(parseMemberVariable)|(parseMemberArrayVariable)|(parseMemberPointerVariable)]
@@ -764,7 +764,6 @@ namespace hex::pl {
// Some kind of variable definition
auto type = parseType();
ON_SCOPE_EXIT { delete type; };
if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)) && sequence<Not>(SEPARATOR_SQUAREBRACKETOPEN))
member = parseMemberArrayVariable(type);
@@ -798,9 +797,11 @@ namespace hex::pl {
// struct Identifier { <(parseMember)...> }
ASTNode* Parser::parseStruct() {
const auto structNode = create(new ASTNodeStruct());
const auto &typeName = getValue<Token::Identifier>(-1).get();
auto structGuard = SCOPE_GUARD { delete structNode; };
const auto structNode = create(new ASTNodeStruct());
const auto typeDecl = addType(typeName, structNode);
auto structGuard = SCOPE_GUARD { delete structNode; delete typeDecl; };
if (MATCHES(sequence(OPERATOR_INHERIT, IDENTIFIER))) {
// Inheritance
@@ -826,14 +827,16 @@ namespace hex::pl {
structGuard.release();
return create(new ASTNodeTypeDecl(typeName, structNode));
return typeDecl;
}
// union Identifier { <(parseMember)...> }
ASTNode* Parser::parseUnion() {
const auto unionNode = create(new ASTNodeUnion());
const auto &typeName = getValue<Token::Identifier>(-2).get();
auto unionGuard = SCOPE_GUARD { delete unionNode; };
const auto unionNode = create(new ASTNodeUnion());
const auto typeDecl = addType(typeName, unionNode);
auto unionGuard = SCOPE_GUARD { delete unionNode; delete typeDecl; };
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
unionNode->addMember(parseMember());
@@ -841,7 +844,7 @@ namespace hex::pl {
unionGuard.release();
return create(new ASTNodeTypeDecl(typeName, unionNode));
return typeDecl;
}
// enum Identifier : (parseType) { <<Identifier|Identifier = (parseMathematicalExpression)[,]>...> }
@@ -852,7 +855,8 @@ namespace hex::pl {
if (underlyingType->getEndian().has_value()) throwParseError("underlying type may not have an endian specification", -2);
const auto enumNode = create(new ASTNodeEnum(underlyingType));
auto enumGuard = SCOPE_GUARD { delete enumNode; };
const auto typeDecl = addType(typeName, enumNode);
auto enumGuard = SCOPE_GUARD { delete enumNode; delete typeDecl; };
if (!MATCHES(sequence(SEPARATOR_CURLYBRACKETOPEN)))
throwParseError("expected '{' after enum definition", -1);
@@ -891,7 +895,7 @@ namespace hex::pl {
enumGuard.release();
return create(new ASTNodeTypeDecl(typeName, enumNode));
return typeDecl;
}
// bitfield Identifier { <Identifier : (parseMathematicalExpression)[;]...> }
@@ -899,7 +903,9 @@ namespace hex::pl {
std::string typeName = getValue<Token::Identifier>(-2).get();
const auto bitfieldNode = create(new ASTNodeBitfield());
auto enumGuard = SCOPE_GUARD { delete bitfieldNode; };
const auto typeDecl = addType(typeName, bitfieldNode);
auto enumGuard = SCOPE_GUARD { delete bitfieldNode; delete typeDecl; };
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
if (MATCHES(sequence(IDENTIFIER, OPERATOR_INHERIT))) {
@@ -920,7 +926,7 @@ namespace hex::pl {
enumGuard.release();
return create(new ASTNodeTypeDecl(typeName, bitfieldNode));
return typeDecl;
}
// (parseType) Identifier @ Integer
@@ -1075,19 +1081,21 @@ namespace hex::pl {
// Consume superfluous semicolons
while (MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)));
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(statement); typeDecl != nullptr) {
auto typeName = getNamespacePrefixedName(typeDecl->getName());
if (this->m_types.contains(typeName))
throwParseError(hex::format("redefinition of type '{}'", typeName));
typeDecl->setName(typeName);
this->m_types.insert({ typeName, typeDecl });
}
return { statement };
}
ASTNodeTypeDecl* Parser::addType(const std::string &name, ASTNode *node, std::optional<std::endian> endian) {
auto typeName = getNamespacePrefixedName(name);
if (this->m_types.contains(typeName))
throwParseError(hex::format("redefinition of type '{}'", typeName));
auto typeDecl = create(new ASTNodeTypeDecl(typeName, node, endian));
this->m_types.insert({ typeName, typeDecl });
return typeDecl;
}
// <(parseNamespace)...> EndOfProgram
std::optional<std::vector<ASTNode*>> Parser::parse(const std::vector<Token> &tokens) {
this->m_curr = tokens.begin();