class ast_iterator

Iterator over the Abstract Syntax Trees (ASTs, ast ) in the tree rooted at a particular ast .

Initialize with ast.traverse().

At any point during traversal with an ast_iterator , ast_traverse_directives can be applied by invoking ast_iterator.apply_directives(). See the ast_iterator.apply_directives() documentation for an example.

Use as you would any other Python iterator. For example:

# set up ast myast, then...
for e in myast.traverse():
    print('ast: ', e)

ast_iterator Details

class cs.ast_iterator

Iterator over the Abstract Syntax Trees (ASTs, ast ) in the tree rooted at a particular ast .

__eq__(other)

Iterator equality.

Parameters:other (ast_iterator) –
Return type:bool
Returns:True if and only if self and other are at the same position. Behavior is undefined if self and other are not iterating over the same collection.
>>> foo = next(p for p in project.current().procedures() if p.name()=='foo')
>>> call = next(p for p in foo.points() if p.get_kind()==point_kind.CALL_SITE)
>>> myastitr = call.get_ast().traverse()
>>> otherastitr = call.get_ast().traverse()
>>> myastitr == otherastitr
True
>>> for a in myastitr:
...    if a.get_class() == ast_class.NC_ADDREXPR:
...       break
...
>>> myastitr == otherastitr
False
__iter__()

Get the iterator object.

Return type:ast_iterator
Returns:self.
>>> v0 = project.current()
>>> v1 = v0.lookup_symbol('foo')
>>> v2 = v1.get_ast()
>>> for it in v2.traverse():  # '__iter__' and '__next__' underlyingly manage iteration
...    if it.get_class()==ast_class.NC_ROUTINE:
...       break
...
>>> it
<cs.ast [c:routine] foo>
__ne__(other)

Iterator inequality.

Parameters:other (ast_iterator) – The iterator to compare against.
Return type:bool
Returns:False if and only if self and other are at the same position. Behavior is undefined if self and other are not iterating over the same collection.
>>> foo = next(p for p in project.current().procedures() if p.name()=='foo')
>>> call = next(p for p in foo.points() if p.get_kind()==point_kind.CALL_SITE)
>>> myastitr = call.get_ast().traverse()
>>> otherastitr = call.get_ast().traverse()
>>> myastitr != otherastitr
False
>>> for a in myastitr:
...    if a.get_class() == ast_class.NC_ADDREXPR:
...       break
...
>>> myastitr != otherastitr
True
__next__()

Iterator dereference operator.

Return type:ast
Returns:The element at the current iterator position.
Raises:StopIteration
  • Side effects: Modifies self.

The typical use is implicit:

>>> for item in myiter:
...   (do something to item)
>>> v0 = project.current()
>>> v1 = v0.lookup_symbol('foo')
>>> v2 = v1.get_ast()
>>> for it in v2.traverse():  # '__iter__' and '__next__' underlyingly manage iteration
...    if it.get_class()==ast_class.NC_ROUTINE:
...       break
...
>>> it
<cs.ast [c:routine] foo>
__repr__()

Get a representation of the iterator that includes information useful for debugging.

Return type:str
Returns:The string representation.
>>> v0 = project.current()
>>> v1 = v0.lookup_symbol('foo')
>>> v2 = v1.get_type()
>>> v3 = v2.traverse()
>>> repr(v3)
'<cs.ast_iterator begin>'
__str__()

Get a simple string representation of the iterator.

Return type:str
Returns:The string representation.
>>> v0 = project.current()
>>> v1 = v0.lookup_symbol('foo')
>>> v2 = v1.get_type()
>>> v3 = v2.traverse()
>>> str(v3)
'<cs.ast_iterator begin>'
apply_directives(directives)

Apply ast_traverse_directives to an ast_iterator .

Parameters:directives (ast_traverse_directives) – the ast_traverse_directives to apply.
Return type:NoneType
  • Side effects: Modifies self.

Invoke at any point during traversal to specify how traversal should proceed from/within the AST ( ast ) at the current iterator position.

>>> cu = next(c for c in project.current().compunits()
...             if c.name().endswith('apitest.cpp'))
>>> proc = next(p for p in cu.procedures() if p.name()=='bar')
>>> # get first call site to bar() in function bar()
>>> csite = next (pt for pt in proc.points()
...               if pt.get_kind()==point_kind.CALL_SITE and pt.callee().name()=='bar')
>>> csite
<cs.point [call-site] bar(int, void *, int)>
>>> # get the actual-in point of rank 2 at csite (because it has a moderately interesting AST)
>>> second_actualin = csite.actual_in(2)
>>> second_actualin
<cs.point [actual-in] $param_2 = (void*)0>
>>> second_actualin_ast = second_actualin.get_ast()
>>> # traverse with no directives
>>> for a in second_actualin_ast.traverse():
...    print(a, '|', a.get_class(), '|', a.children())
...
$param_2 = (void*)0 | c:= | (<cs.ast_field 1:[c:variable] $param_2>, <cs.ast_field 2:[c:cast] (void*)0>)
$param_2 | c:variable | (<cs.ast_field name:$param_2>,)
(void*)0 | c:cast | (<cs.ast_field 1:[c:pointer] void*>, <cs.ast_field 2:[c:integer-value-32] 0>)
void* | c:pointer | ()
0 | c:integer-value-32 | (<cs.ast_field value:0>,)
>>> # traverse, skipping over children of c:cast ASTs
>>> astiter = second_actualin_ast.traverse()
>>> for a in astiter:
...    if a.get_class() == ast_class.NC_CASTEXPR:
...       astiter.apply_directives(ast_traverse_directives.SKIP_CHILDREN)
...    print(a, '|', a.get_class(), '|', a.children())
...
$param_2 = (void*)0 | c:= | (<cs.ast_field 1:[c:variable] $param_2>, <cs.ast_field 2:[c:cast] (void*)0>)
$param_2 | c:variable | (<cs.ast_field name:$param_2>,)
(void*)0 | c:cast | (<cs.ast_field 1:[c:pointer] void*>, <cs.ast_field 2:[c:integer-value-32] 0>
at_end()

Check: is the iterator at the end of the structure?

Return type:bool
Returns:True if the iterator is at the end of the structure (there are no more elements to iterate over), False otherwise.
>>> v0 = project.current()
>>> v1 = v0.lookup_symbol('foo')
>>> v2 = v1.get_ast()
>>> v3 = v2.traverse()
>>> v3.at_end()
False