1
0
mirror of synced 2024-09-25 12:08:26 +02:00

patterns: Allow forward declaring of types

This commit is contained in:
WerWolv 2022-03-24 16:57:12 +01:00
parent c2803fe1e2
commit c09d85f46d
4 changed files with 46 additions and 13 deletions

View File

@ -8,6 +8,8 @@ namespace hex::pl {
class ASTNodeTypeDecl : public ASTNode,
public Attributable {
public:
ASTNodeTypeDecl(std::string name) : m_forwardDeclared(true), m_name(name) { }
ASTNodeTypeDecl(std::string name, std::shared_ptr<ASTNode> type, std::optional<std::endian> endian = std::nullopt)
: ASTNode(), m_name(std::move(name)), m_type(std::move(type)), m_endian(endian) { }
@ -69,7 +71,18 @@ namespace hex::pl {
Attributable::addAttribute(std::move(attribute));
}
[[nodiscard]]
bool isForwardDeclared() const {
return this->m_forwardDeclared;
}
void setType(std::shared_ptr<ASTNode> type) {
this->m_forwardDeclared = false;
this->m_type = type;
}
private:
bool m_forwardDeclared = false;
std::string m_name;
std::shared_ptr<ASTNode> m_type;
std::optional<std::endian> m_endian;

View File

@ -34,7 +34,7 @@ namespace hex::pl {
TokenIter m_curr;
TokenIter m_originalPosition, m_partOriginalPosition;
std::unordered_map<std::string, std::shared_ptr<ASTNode>> m_types;
std::unordered_map<std::string, std::shared_ptr<ASTNodeTypeDecl>> m_types;
std::vector<TokenIter> m_matchedOptionals;
std::vector<std::vector<std::string>> m_currNamespace;
@ -121,6 +121,7 @@ namespace hex::pl {
std::shared_ptr<ASTNodeTypeDecl> parseUnion();
std::shared_ptr<ASTNodeTypeDecl> parseEnum();
std::shared_ptr<ASTNodeTypeDecl> parseBitfield();
void parseForwardDeclaration();
std::unique_ptr<ASTNode> parseVariablePlacement(const std::shared_ptr<ASTNodeTypeDecl> &type);
std::unique_ptr<ASTNode> parseArrayVariablePlacement(const std::shared_ptr<ASTNodeTypeDecl> &type);
std::unique_ptr<ASTNode> parsePointerVariablePlacement(const std::shared_ptr<ASTNodeTypeDecl> &type);

View File

@ -706,10 +706,7 @@ namespace hex::pl {
// using Identifier = (parseType)
std::shared_ptr<ASTNodeTypeDecl> Parser::parseUsingDeclaration() {
auto name = parseNamespaceResolution();
if (!MATCHES(sequence(OPERATOR_ASSIGNMENT)))
throwParserError("expected '=' after type name of using declaration");
auto name = getNamespacePrefixedName(getValue<Token::Identifier>(-2).get());
auto type = parseType();
@ -976,6 +973,16 @@ namespace hex::pl {
return typeDecl;
}
// using Identifier;
void Parser::parseForwardDeclaration() {
std::string typeName = getNamespacePrefixedName(getValue<Token::Identifier>(-1).get());
if (this->m_types.contains(typeName))
return;
this->m_types.insert({ typeName, create(new ASTNodeTypeDecl(typeName) )});
}
// (parseType) Identifier @ Integer
std::unique_ptr<ASTNode> Parser::parseVariablePlacement(const std::shared_ptr<ASTNodeTypeDecl> &type) {
bool inVariable = false;
@ -1088,8 +1095,10 @@ namespace hex::pl {
std::vector<std::shared_ptr<ASTNode>> Parser::parseStatements() {
std::shared_ptr<ASTNode> statement;
if (MATCHES(sequence(KEYWORD_USING, IDENTIFIER)))
if (MATCHES(sequence(KEYWORD_USING, IDENTIFIER, OPERATOR_ASSIGNMENT)))
statement = parseUsingDeclaration();
else if (MATCHES(sequence(KEYWORD_USING, IDENTIFIER)))
parseForwardDeclaration();
else if (peek(IDENTIFIER)) {
auto originalPos = this->m_curr;
this->m_curr++;
@ -1118,7 +1127,7 @@ namespace hex::pl {
return parseNamespace();
else throwParserError("invalid sequence", 0);
if (MATCHES(sequence(SEPARATOR_SQUAREBRACKETOPEN, SEPARATOR_SQUAREBRACKETOPEN)))
if (statement && MATCHES(sequence(SEPARATOR_SQUAREBRACKETOPEN, SEPARATOR_SQUAREBRACKETOPEN)))
parseAttribute(dynamic_cast<Attributable *>(statement.get()));
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
@ -1128,19 +1137,28 @@ namespace hex::pl {
while (MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
;
if (!statement)
return { };
return hex::moveToVector(std::move(statement));
}
std::shared_ptr<ASTNodeTypeDecl> Parser::addType(const std::string &name, std::unique_ptr<ASTNode> &&node, std::optional<std::endian> endian) {
auto typeName = getNamespacePrefixedName(name);
if (this->m_types.contains(typeName))
throwParserError(hex::format("redefinition of type '{}'", typeName));
if (this->m_types.contains(typeName) && this->m_types.at(typeName)->isForwardDeclared()) {
this->m_types.at(typeName)->setType(std::move(node));
std::shared_ptr typeDecl = create(new ASTNodeTypeDecl(typeName, std::move(node), endian));
this->m_types.insert({ typeName, typeDecl });
return this->m_types.at(typeName);
} else {
if (this->m_types.contains(typeName))
throwParserError(hex::format("redefinition of type '{}'", typeName));
return typeDecl;
std::shared_ptr typeDecl = create(new ASTNodeTypeDecl(typeName, std::move(node), endian));
this->m_types.insert({ typeName, typeDecl });
return typeDecl;
}
}
// <(parseNamespace)...> EndOfProgram

View File

@ -33,7 +33,8 @@ namespace hex::pl {
if (!types.insert(typeDeclNode->getName().data()).second)
throwValidatorError(hex::format("redefinition of type '{0}'", typeDeclNode->getName().data()), typeDeclNode->getLineNumber());
this->validate(hex::moveToVector<std::shared_ptr<ASTNode>>(typeDeclNode->getType()->clone()));
if (!typeDeclNode->isForwardDeclared())
this->validate(hex::moveToVector<std::shared_ptr<ASTNode>>(typeDeclNode->getType()->clone()));
} else if (auto structNode = dynamic_cast<ASTNodeStruct *>(node.get()); structNode != nullptr) {
this->validate(structNode->getMembers());
} else if (auto unionNode = dynamic_cast<ASTNodeUnion *>(node.get()); unionNode != nullptr) {