cinspector.nodes package

Submodules

cinspector.nodes.abstract_node module

class cinspector.nodes.abstract_node.AbstractNode(node_type=None)[source]

Bases: Node

AbstractNode is the base class of abstract node classes. The so-called abstract node is the node that exists for the convenience of analysis (for example, CFG generation). It doesn’t correspond to the acutal code elemetnts.

class cinspector.nodes.abstract_node.BorderNode(node_type=None)[source]

Bases: AbstractNode

class cinspector.nodes.abstract_node.DoWhileLoopNode(condition, node_type='loop_condition')[source]

Bases: AbstractNode

Used to represent the condition of do-while loop

class cinspector.nodes.abstract_node.ForLoopNode(initializer, condition, update, node_type='loop_condition')[source]

Bases: AbstractNode

descendants_by_type_name(name)[source]
class cinspector.nodes.abstract_node.IfConditionNode(condition, node_type='if_condition')[source]

Bases: AbstractNode

common_entry_constraints()[source]

Many possible entry constraints exist for one condition. There are some strong constraints that are contained in every entry constraint.

For example, for condition if (a < 1 && (b < 0 || b > 1)), it contains entry constraints [[a < 1, b < 0], [a < 1, b > 1]], a < 1 is a strong constraint. In other word, it is a must obeyed constraint.

This function also a one-dimension list.

descendants_by_type_name(type_name)[source]
entry_constraints()[source]

output the constraints for going into the condition it returns a two-dimension list

if (a || (a < 1 && a > 0)) -> (a) (a < 1, a > 0) if (b && (a < 1 || a > 0)) -> (b, a < 1) (b, a > 0)

class cinspector.nodes.abstract_node.NConditionNode(condition, node_type='n_if')[source]

Bases: IfConditionNode

class cinspector.nodes.abstract_node.NForLoopNode(initializer, condition, update, node_type='n_loop')[source]

Bases: ForLoopNode

class cinspector.nodes.abstract_node.NWhileLoopNode(condition, node_type='n_loop')[source]

Bases: WhileLoopNode

class cinspector.nodes.abstract_node.SwitchNode(condition, case_value, node_type='switch_node')[source]

Bases: AbstractNode

descendants_by_type_name(types)[source]
class cinspector.nodes.abstract_node.WhileLoopNode(condition, node_type='loop_condition')[source]

Bases: AbstractNode

descendants_by_type_name(name)[source]
class cinspector.nodes.abstract_node.YConditionNode(condition, node_type='y_if')[source]

Bases: IfConditionNode

class cinspector.nodes.abstract_node.YForLoopNode(initializer, condition, update, node_type='y_loop')[source]

Bases: ForLoopNode

class cinspector.nodes.abstract_node.YWhileLoopNode(condition, node_type='y_loop')[source]

Bases: WhileLoopNode

cinspector.nodes.basic_node module

This file contains wrapper classes of tree-sitter nodes. In general, the wrapper classes are designed following the following rules:

1. Naming Convention. The class is named based on the type of tree-sitter node. For example, the wrapper class of tree-sitter node ‘function_definition’ is named FunctionDefinitionNode.

2. Attributes. The attributes within each class can by divided into two groups. The first group corresponds to the fields of tree-sitter node. For example, the node of ‘function_definition’ type in tree-sitter has the fields ‘type’, ‘declarator’, and ‘body’. The wrapper class of ‘function_definition’ FunctionDefinitionNode will also contain the attributes ‘type’, ‘declarator’, and ‘body’. The second group of attributes is added by cinspector to facilitate the analysis of source code. We call them additional attributes.

3. Property representation. The properties of the node classes in this file, i.e., classes inheriting from BasicNode, should be represented by BasicNode instances as much as possible. For example, the property ‘name’ of the class ParameterDeclarationNode is an instance of IdentifierNode instead of str. Of course, the user can also get the str format by invoking the method src().

class cinspector.nodes.basic_node.AssignmentExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

property symbol: str

Return the symbol of the assignment expression, e.g., a |= b owns the symbol |=.

class cinspector.nodes.basic_node.BasicNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: Node, Util, Query

The ancestor of all wrapper classes of tree-sitter nodes

For those tree-sitter nodes that do not have corresponding wrapper, they use BasicNode as the default wrapper.

Pay attention to the difference betweeen <internal_src> and <src>. Considering the way cinspector is used, every BasicNode (or its subclass) belongs to a code snippet. The <internal_src> stores the source code of the whole code snippet while src stores the source code of the current node. For example, if we have a code snippet:

int a; int func() {return 0;}

Assume func_node represents the function <func> in the code snippet and is an instance of FunctionDefinitionNode. Then, the <src> of func_node is ‘int func() {return 0;}’. While the <internal_src> of func_node is the whole code snippet.

internal_src

the source code of the whole code snippet.

Type:

str

internal

the corresponding tree-sitter node of the current wrapper class.

Type:

tree_sitter.Node

internal_tree

the corresponding tree-sitter tree of the whole code snippet, internal belongs to this tree.

Type:

tree_sitter.Tree

node_type

the type of the current wrapper class.

Type:

str

ts_type

deprecated, type of the corresponding tree-sitter node, we design this since the wrapper class and corresponding tree-sitter node may have different type under some situations.

Type:

str

start_point

the start position of the current node in internal_src.

Type:

tuple

end_point

the end position of the current node in internal_src.

Type:

tuple

child_count

the number of children of the current node.

Type:

int

src

the source code of the current node.

Type:

str

Properties:

parent (BasicNode): the parent node of the current node. children (List[BasicNode]): the children nodes of the current node.

equal(_o

‘BasicNode’): check whether the current node is equal to _o.

make_wrapper(ts_node

tree-sitter.Node): make a wrapper class for the tree-sitter node.

child_by_field_name(field_name

str): get the specific field of the current node.

descendants()[source]

get all descendants.

descendants_by_type_name(type_name

Union[str, List[str]): get the descendants nodes belonging to the specific type.

print_tree()[source]

print the parsed tree

child_by_field_name(name: str)[source]
property children

DO NOT use this attribute on huge BasicNode such as ndoe of file, otherwise horrible recursion.

descendants()[source]

Depth-first traverse to collect all descendants of the current node, the current node itself will not be collected.

descendants_by_type_name(name: str | List[str])[source]

Depth-first traverse to collect all descendants that satisfy the node_type requirements.

equal(_o: BasicNode) bool[source]
in_front(node: BasicNode)[source]
internal_src

Ideally, the following condtion is true only when file content is passed to BasicNode. Other nodes such as FunctionDefinitionNode should be initialized with ts_node dictated.

make_wrapper(ts_node)[source]
property parent
print_tree()[source]

Print the parsed tree

tokenize() List[BasicNode][source]

Tokenize the current code snippet

Returns:

A list (order-sensitive) of tokens

class cinspector.nodes.basic_node.BinaryExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

is_logic_op()[source]
class cinspector.nodes.basic_node.CallExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

is_indirect() bool[source]

whether the invocation is the indirect call

class cinspector.nodes.basic_node.CaseExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.CompoundStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

The wrapper of tree-sitter node ‘compound_statement’.

CompoundStatementNode is a collection of nodes. For example, it is used to represent the body of the function and loop node.

statements

the nodes contained in compound statement

Type:

list

class cinspector.nodes.basic_node.ConditionalExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.DeclarationNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

declared_identifiers() List[IdentifierNode][source]
class cinspector.nodes.basic_node.DoStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.EnumSpecifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

wrapper of the tree-sitter node with the type <enum_specifier>

Note that EnumSpecifierNode has different formats:

  1. enum Hash { A, B}; -> the whole string except ‘;’ is EnumSpecifierNode

  2. void func(enum Hash h); -> <enum Hash> is EnumSpecifierNode, currently

    this node has no filed <body>

conclude_value(value_dic={}) dict[source]

While self.kv provides the literal enum key and value, conclude_value tries to conclude the actual values that keys represent.

For example, for the following enumeration:
enum A {

A1 = MACRO1, // #define MACRO1 1 A2,

};

self.kv equals to {A1: MACRO1, A2: None}.

However, with the value of MACRO1 provided by the parameter value_dic, conclude_value will output the dict like {A1: 1, A2: 2}.

unsolved_value()[source]

helper function of conclude_value, outputs the symbols representing unknown values. One needs to provide the values of these symbols to perform conclude_value.

class cinspector.nodes.basic_node.EnumeratorListNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.EnumeratorNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.ExpressionStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.FieldDeclarationListNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for field_declaration_list node in tree-sitter

One can get all field_declaration by children()

class cinspector.nodes.basic_node.FieldDeclarationNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for field_declaration node in tree-sitter

class cinspector.nodes.basic_node.FieldIdentifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for field_identifier node in tree-sitter

class cinspector.nodes.basic_node.ForStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.FunctionDeclaratorNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

wrapper of the function_declarator node in tree-sitter

declarator

declarator

Type:

BasicNode

parameters

parameters

Type:

ParameterListNode

class cinspector.nodes.basic_node.FunctionDefinitionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper class of the function_definition node in tree-sitter

type

the type of the function

Type:

TypeNode

declarator

the declarator of the function

Type:

FunctionDeclaratorNode

body

the body of the function

Type:

CompoundStatementNode

TODO: name may be None under some cases

property inline: bool

Whether the function is inline

property name: IdentifierNode

conclude the name of the function

property parameters: ParameterListNode

conclude the parameters of the function

The node function_declarator in tree-sitter has two fields: declarator and parameters. However, the field parameters is not strictly the real parameters of the current function. For example, for the function int (*bar(int a))(int), the field parameters of the function_declarator (*bar(int a))(int) is (int), while int a is the real parameter of the function.

property static: bool

Whether the function is static

property storage_class_specifier: List[StorageClassSpecifierNode]

get the storage class specifier of the parameter

property type_qualifier: List[TypeQualifierNode]

get the type qualifier of the parameter

class cinspector.nodes.basic_node.IdentifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.IfStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

common_entry_constraints()[source]
entry_constraints()[source]
class cinspector.nodes.basic_node.InitDeclaratorNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.NumberLiteralNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.ParameterDeclarationNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

The wrapper of the parameter_declaration node in tree-sitter.

type

the type of the parameter.

Type:

TypeNode

declarator

the declarator of the parameter, this can be None, e.g. int func(void), or the declaration int func(int).

Type:

Optional[BasicNode]

property name: IdentifierNode | None

try to analyse the name of the parameter

property storage_class_specifier: List[StorageClassSpecifierNode]

get the storage class specifier of the parameter

property type_qualifier: List[TypeQualifierNode]

get the type qualifier of the parameter

class cinspector.nodes.basic_node.ParameterListNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

The wrapper of the parameter_list node in tree-sitter.

ParameterListNode is a collection of ParameterDeclarationNode. You can visit the children of ParameterListNode by the attributes <children>.

class cinspector.nodes.basic_node.ParenthesizedExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

remove_parenthese()[source]
class cinspector.nodes.basic_node.PreprocArgNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.PreprocDefNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.PreprocFunctionDefNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.ReturnStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.StorageClassSpecifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for storage class specifier node in tree-sitter

Every variable has two properties in C language that are: data type (int, char, float, etc.) and storage class. The Storage Class of a variable decides its scope, lifetime, storage location, and default value.

There are four storage classes in C language: auto, extern, static, and register.

class cinspector.nodes.basic_node.StructSpecifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for struct_specifier node in Tree-sitter

class cinspector.nodes.basic_node.SubscriptExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.TypeIdentifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for type_identifier node in tree-sitter

class cinspector.nodes.basic_node.TypeNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

TODO: remove the pointer_level and array_level, use analysis module to conclude the related property.

is_array()[source]
is_pointer()[source]
class cinspector.nodes.basic_node.TypeQualifierNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

Wrapper for type qualifier node in tree-sitter

A type qualifier is a keyword that is applied to a type, resulting in a qualified type.

As of 2014 and C11, there are four type qualifiers in standard C: const (C89), volatile (C89), restrict (C99) and _Atomic (C11)

class cinspector.nodes.basic_node.UnaryExpressionNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

used_ids()[source]
class cinspector.nodes.basic_node.VariadicParameterNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

class cinspector.nodes.basic_node.WhileStatementNode(src: str, ts_node=None, ts_tree=None)[source]

Bases: BasicNode

cinspector.nodes.edit module

Edit nodes

class cinspector.nodes.edit.Edit(target: BasicNode)[source]

Bases: Util

Edit the BasicNode

This class is designed for editing the BasicNode, including adding, deleting, and replacing the children.

is_child(child: BasicNode) bool[source]

whether the child node is the child of self.target, check by 1. same tree_sitter.Tree 2. start and end point

remove_child(child: BasicNode)[source]

Remove the child from the target node

Parameters:

child – the child to be removed

class cinspector.nodes.edit.EditPos(start: int, end: int, new_snippet: str)[source]

Bases: object

cinspector.nodes.edit.edit_str(s: str, edits: List[EditPos]) str | None[source]

cinspector.nodes.node module

Make a wrapper of tree-sitter node

class cinspector.nodes.node.Node[source]

Bases: object

The root calss of all nodes

In general, there are three types of nodes. Node is the root class of all nodes while both AbstractNode and BasicNode are the direct children of Node.

AbstractNode represents the logical node in the source code. It does not correspond to a exactly same element in the source code. We design AbstractNode mainly for the needs of program analysis.

BasicNode is the base class of a series of nodes that correspond to the actually existing elements in the source code.

class cinspector.nodes.node.Query[source]

Bases: object

Access the specific nodes in the source code

Query is used to access the nodes with specific properties in the source code. For example, find the enumeration with the type identifier “weekdays”. To implement this, we let EnumSpecifierNode inherit from Query and implement the __type_identifier_result method, i.e., returns the field <name>. The class in interface such as CCode will gather all the EnumSpecifierNode and check the query method to find the ideal node.

mapping

a dictionary that maps the query key to the method

query()[source]

query the node with the given query

query(query: Dict[str, str]) bool[source]

Query the node with the given query

Parameters:

query – the query to be executed

Returns:

True if the node satisfies the query, otherwise False

class cinspector.nodes.node.Util[source]

Bases: object

sort_nodes(nodes

Iterable, reverse: bool = False): sort the nodes by their position in internal_src.

get_cursor(src: str)[source]
static get_node_raw(s: str, node)[source]
get_parser()[source]
static get_raw(s: str, start: tuple, end: tuple) str | None[source]

extracts from s the string fragment specified by the points start and end

Parameters:
  • s (str) – a string

  • start (tuple) – (row, column), specify the start of the fragment

  • end (tuple) – (row, column), specify the end of the fragment

Returns:

the extracted string, or None if it fails

get_tree(src: str)[source]
static point2index(s: str, row: int, col: int) int | None[source]

return the character index at the specified row and column in the string s.

Parameters:
  • s (str) – a string

  • row (int) – row, start from 0

  • col (int) – column, start from 0

Returns:

the character index, or None if it fails

static sort_nodes(nodes: Iterable, reverse: bool = False) Iterable[source]

Sort the instances of BasicNode by their position in source code

Parameters:
  • nodes (Iterable) – nodes waiting for sorting

  • reverse (bool=False) – use descending instead of ascending

Returns:

sorted Iterable object

Module contents