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)
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)
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
foois after a node of classbar: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
foois before a node of classbar: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
foois an ancestor of a node of classbar: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
foois a descendant of a node of classbar:Cpp.foo.is(&fn) and fn.toNode(&fnode) and Cpp.bar.is(&bn) and bn.toNode(&bnode) and fnode.isDescendantOf(bnode)