patterns: Allow forward declaring of types
This commit is contained in:
parent
c2803fe1e2
commit
c09d85f46d
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,12 +1137,20 @@ 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) && this->m_types.at(typeName)->isForwardDeclared()) {
|
||||
this->m_types.at(typeName)->setType(std::move(node));
|
||||
|
||||
return this->m_types.at(typeName);
|
||||
} else {
|
||||
if (this->m_types.contains(typeName))
|
||||
throwParserError(hex::format("redefinition of type '{}'", typeName));
|
||||
|
||||
@ -1142,6 +1159,7 @@ namespace hex::pl {
|
||||
|
||||
return typeDecl;
|
||||
}
|
||||
}
|
||||
|
||||
// <(parseNamespace)...> EndOfProgram
|
||||
std::optional<std::vector<std::shared_ptr<ASTNode>>> Parser::parse(const std::vector<Token> &tokens) {
|
||||
|
@ -33,6 +33,7 @@ namespace hex::pl {
|
||||
if (!types.insert(typeDeclNode->getName().data()).second)
|
||||
throwValidatorError(hex::format("redefinition of type '{0}'", typeDeclNode->getName().data()), typeDeclNode->getLineNumber());
|
||||
|
||||
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());
|
||||
|
Loading…
Reference in New Issue
Block a user