주요 콘텐츠

Traverse Syntax Tree Using Polyspace Query Language

Syntax issues are often detected by identifying specific relationship between various syntax nodes. That is, detecting syntax issues often require detecting specific parent-child relationship patterns in the syntax tree. This topic shows techniques you can use to detect relationship between two nodes in the syntax tree. For checking relationships between syntax nodes, use the predicates of the class AstNodeProperties.

Check Parent-Child Relations

Say you identify a syntax node. You can then retrieve its child node and check if the child node is a specific syntax class.

For example, consider this code. A syntax node fn of foo class is identified using the is predicate. This node is then converted to a Node class to access predicates of AstNodeProperties.

Cpp.foo.is(&fn)
and fn.toNode(&node)
and node.getAChild(&child)
and Cpp.bar.isa(child)
Then, the child node of fn retrieved using getAChild. Once you find the child node as a generic Node, you can then test if the child is of a specific syntax class. This code checks if the child is a bar type.

Similarly, you can check if the parent of a syntax node is a specific syntax class. In this code, after identifying nodes of class foo, the parent node is retrieved and checked,

Cpp.foo.is(&fn)
and fn.toNode(&node)
and node.parent(&child)
and Cpp.bar.isa(child)

Check Ancestor-Descendant Relations

After identifying a syntax node, you can check if any of its ancestors or descendents is of a specific class. For example, this code checks if any ancestor of fn is a bar class.

Cpp.foo.is(&fn)
and fn.toNode(&node)
and node.getAnAncestor(&child)
and Cpp.bar.isa(child)
Similarly, this code checks if any descendant of fn is a bar class:
Cpp.foo.is(&fn)
and fn.toNode(&node)
and node.getADescendant(&child)
and Cpp.bar.isa(child)

Check Relative Positions in Syntax Tree

After identifying a syntax node, you can check if it is positioned before or after a specific node.

  • Check of a node of class foo is after a node of class bar:

    Cpp.foo.is(&fn)
    and fn.toNode(&fnode)
    and Cpp.bar.is(&bn)
    and bn.toNode(&bnode)
    and fnode.isAfterInAST(bnode)

  • Check of a node of class foo is before a node of class bar:

    Cpp.foo.is(&fn)
    and fn.toNode(&fnode)
    and Cpp.bar.is(&bn)
    and bn.toNode(&bnode)
    and fnode.isBeforeInAST(bnode)

  • Check of a node of class foo is an ancestor of a node of class bar:

    Cpp.foo.is(&fn)
    and fn.toNode(&fnode)
    and Cpp.bar.is(&bn)
    and bn.toNode(&bnode)
    and fnode.isAncestorOf(bnode)

  • Check of a node of class foo is a descendant of a node of class bar:

    Cpp.foo.is(&fn)
    and fn.toNode(&fnode)
    and Cpp.bar.is(&bn)
    and bn.toNode(&bnode)
    and fnode.isDescendantOf(bnode)

See Also

Topics