From 5f8176804d97155dce4fa7ccd3961d4319a4e026 Mon Sep 17 00:00:00 2001 From: Julien FAUCHER Date: Fri, 1 Mar 2024 15:26:24 +0100 Subject: [PATCH] Implements getChildPtr Allows to retrieve a mutable version of a token of any SyntaxNode, and in particular the first and last token. --- include/slang/syntax/SyntaxNode.h | 18 ++++++++++++ scripts/syntax_gen.py | 31 +++++++++++++++++---- source/syntax/SyntaxNode.cpp | 46 +++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/include/slang/syntax/SyntaxNode.h b/include/slang/syntax/SyntaxNode.h index a62d6d666..32a6bbd82 100644 --- a/include/slang/syntax/SyntaxNode.h +++ b/include/slang/syntax/SyntaxNode.h @@ -107,6 +107,12 @@ class SLANG_EXPORT SyntaxNode { /// Get the last leaf token in this subtree. Token getLastToken() const; + /// Get the first leaf token as a mutable pointer in this subtree. + Token* getFirstTokenPtr(); + + /// Get the last leaf token a mutable pointer in this subtree. + Token* getLastTokenPtr(); + /// Get the source range of the node. SourceRange sourceRange() const; @@ -185,6 +191,7 @@ class SLANG_EXPORT SyntaxNode { private: ConstTokenOrSyntax getChild(size_t index) const; TokenOrSyntax getChild(size_t index); + PtrTokenOrSyntax getChildPtr(size_t index); }; /// @brief Performs a shallow clone of the given syntax node. @@ -260,6 +267,9 @@ class SLANG_EXPORT SyntaxListBase : public SyntaxNode { /// Gets the child (token or node) at the given index. virtual ConstTokenOrSyntax getChild(size_t index) const = 0; + // Gets the child pointer (token or node) at given index. + virtual PtrTokenOrSyntax getChildPtr(size_t index) = 0; + /// Sets the child (token or node) at the given index. virtual void setChild(size_t index, TokenOrSyntax child) = 0; @@ -289,6 +299,7 @@ class SLANG_EXPORT SyntaxList : public SyntaxListBase, public std::span { private: TokenOrSyntax getChild(size_t index) final { return (*this)[index]; } ConstTokenOrSyntax getChild(size_t index) const final { return (*this)[index]; } + PtrTokenOrSyntax getChildPtr(size_t index) final {return (*this)[index];}; void setChild(size_t index, TokenOrSyntax child) final { (*this)[index] = &child.node()->as(); @@ -327,6 +338,7 @@ class SLANG_EXPORT TokenList : public SyntaxListBase, public std::span(elements[index])); + } void setChild(size_t index, TokenOrSyntax child) final { elements[index] = child; } SyntaxListBase* clone(BumpAllocator& alloc) const final { diff --git a/scripts/syntax_gen.py b/scripts/syntax_gen.py index d221ef9c0..5ae437d62 100755 --- a/scripts/syntax_gen.py +++ b/scripts/syntax_gen.py @@ -367,6 +367,7 @@ def generateSyntax(builddir, alltypes, kindmap): outf.write(" TokenOrSyntax getChild(size_t index);\n") outf.write(" ConstTokenOrSyntax getChild(size_t index) const;\n") + outf.write(" PtrTokenOrSyntax getChildPtr(size_t index);\n") outf.write(" void setChild(size_t index, TokenOrSyntax child);\n\n") docf.write( @@ -382,6 +383,14 @@ def generateSyntax(builddir, alltypes, kindmap): name ) ) + docf.write( + " @brief Gets the child member (token or syntax node) as a pointer at the provided index within this struct\n" + ) + docf.write( + " @fn PtrTokenOrSyntax slang::syntax::{}::getChildPtr(size_t index)\n".format( + name + ) + ) docf.write( " @brief Gets the child member (token or syntax node) at the provided index within this struct\n" ) @@ -473,23 +482,32 @@ def generateSyntax(builddir, alltypes, kindmap): cppf.write("}\n\n") if v.members or v.final != "": - for returnType in ("TokenOrSyntax", "ConstTokenOrSyntax"): + for returnType in ("TokenOrSyntax", "ConstTokenOrSyntax", "PtrTokenOrSyntax"): cppf.write( - "{} {}::getChild(size_t index){} {{\n".format( - returnType, k, "" if returnType == "TokenOrSyntax" else " const" + "{} {}::getChild{}(size_t index){} {{\n".format( + returnType, k, ("Ptr" if returnType.startswith("Ptr") else ""), "" if not returnType.startswith("Const") else " const" ) ) + returnPointer = returnType == "PtrTokenOrSyntax" + if v.combinedMembers: cppf.write(" switch (index) {\n") index = 0 for m in v.combinedMembers: - addr = "&" if m[1] in v.pointerMembers else "" + addr = "" + if returnPointer : + if m[0] == "Token" or (m[1] in v.pointerMembers): + addr = "&" + elif m[1] in v.pointerMembers : + addr = "&" + + # addr = "&" if != (returnPointer and not (m[1] in v.notNullMembers)) else "" get = ".get()" if m[1] in v.notNullMembers else "" cppf.write( - " case {}: return {}{}{};\n".format( - index, addr, m[1], get + " case {}: return {}{}{}; //{}\n".format( + index, addr, m[1], get, f"ptr = {m[1] in v.pointerMembers}, nn={m[1] in v.notNullMembers}" ) ) index += 1 @@ -636,6 +654,7 @@ def generateSyntax(builddir, alltypes, kindmap): ) outf.write(" TokenOrSyntax getChild(size_t) { return nullptr; }\n") outf.write(" ConstTokenOrSyntax getChild(size_t) const { return nullptr; }\n") + outf.write(" PtrTokenOrSyntax getChildPtr(size_t) { return nullptr; }\n") outf.write(" void setChild(size_t, TokenOrSyntax) {}\n") outf.write("};\n\n") diff --git a/source/syntax/SyntaxNode.cpp b/source/syntax/SyntaxNode.cpp index aafc8b73a..e6ead4d4f 100644 --- a/source/syntax/SyntaxNode.cpp +++ b/source/syntax/SyntaxNode.cpp @@ -15,6 +15,13 @@ namespace { using namespace slang; using namespace slang::syntax; +struct PtrGetChildVisitor { + template + PtrTokenOrSyntax visit(T& node, size_t index) { + return node.getChildPtr(index); + } +}; + struct ConstGetChildVisitor { template ConstTokenOrSyntax visit(const T& node, size_t index) { @@ -86,6 +93,40 @@ parsing::Token SyntaxNode::getLastToken() const { return Token(); } +parsing::Token* SyntaxNode::getFirstTokenPtr() { + size_t childCount = getChildCount(); + for (size_t i = 0; i < childCount; i++) { + auto child = getChildPtr(i); + if (child.isToken()) { + if (child.token()) + return child.token(); + } + else if (child.node()) { + auto result = child.node()->getFirstTokenPtr(); + if (result) + return result; + } + } + return nullptr; +} + +parsing::Token* SyntaxNode::getLastTokenPtr() { + size_t childCount = getChildCount(); + for (ptrdiff_t i = ptrdiff_t(childCount) - 1; i >= 0; i--) { + auto child = getChildPtr(size_t(i)); + if (child.isToken()) { + if (child.token()) + return child.token(); + } + else if (child.node()) { + auto result = child.node()->getLastTokenPtr(); + if (result) + return result; + } + } + return nullptr; +} + SourceRange SyntaxNode::sourceRange() const { Token firstToken = getFirstToken(); Token lastToken = getLastToken(); @@ -97,6 +138,11 @@ ConstTokenOrSyntax SyntaxNode::getChild(size_t index) const { return visit(visitor, index); } +PtrTokenOrSyntax SyntaxNode::getChildPtr(size_t index) { + PtrGetChildVisitor visitor; + return visit(visitor, index); +} + TokenOrSyntax SyntaxNode::getChild(size_t index) { GetChildVisitor visitor; return visit(visitor, index);