"""Declarations Abstract Syntax Tree (AST)
This file provides the definitions of various nodes used to represent a C syntax tree.
It is utilized by `pycparser` to construct and process abstract syntax trees (ASTs) for C code.
The nodes defined here implement the visitor pattern, allowing tree traversal and manipulation.
Based on the c_ast.py from the pycparser project by Eli Bendersky (https://eli.thegreenplace.net)
under the BSD license.
This file can be imported and contains the following classes:
* Node: Abstract base class for all AST nodes.
* NodeVisitor: Base class for visitor implementations for traversing AST nodes.
* ArrayDecl: Represents an array declaration node.
* ArrayRef: Represents an array reference node.
* Assignment: Represents an assignment operation node.
* BinaryOp: Represents a binary operation node.
* Compound: Represents a compound statement node.
* CompoundLiteral: Represents a compound literal node.
* Decl: Represents a declaration node.
* DeclList: Represents a list of declarations node.
* EmptyStatement: Represents an empty statement node.
* ExprList: Represents a list of expressions node.
* FileAST: Represents the root node of the syntax tree, containing the file's AST.
* FuncCall: Represents a function call node.
* FuncDecl: Represents a function declaration node.
* FuncDef: Represents a function definition node.
* ID: Represents an identifier node.
* IdentifierType: Represents a type identifier node.
* InitList: Represents an initialization list node.
* NamedInitializer: Represents a named initializer node.
* ParamList: Represents a list of parameters node.
* RangeDecl: Represents a range declaration node.
* Return: Represents a return statement node.
* Struct: Represents a struct declaration node.
* StructRef: Represents a struct reference node.
* TypeDecl: Represents a type declaration node.
* Typedef: Represents a type definition node.
* Typename: Represents a type name node.
* UnaryOp: Represents a unary operation node.
The classes marked by a "#" (DoWhile, For, If, While) were kept from the original
implementation for the C programming language together with the respective rules in the
Declaration Parser. This means UPPAAL code with loops and if statements is parsable
and results in a correct AST.
However, the NodeVisitor does not support them as they were no use case for the
uppaal2jetracer project. In consequence neither the Executor nor the Tree Visitor support them.
To support the execution of those control structures, the NodeVisitor needs to be extended
and their functionality needs to be implemented in the Executor.
"""
from __future__ import annotations
from abc import ABC, abstractmethod
import logging
from uppaal2jetracer.parser.declarationparser.plyparser import Coord
logger = logging.getLogger("declarations")
[docs]
class Node(ABC):
"""
Abstract base class for AST nodes.
Each node represents a specific construct in the C code
and can be visited using a `NodeVisitor`.
"""
__slots__ = ()
def __init__(self):
logger.debug("Created %s node: %s", self.__class__.__name__, self)
def __repr__(self):
"""
Generates a string representation of the node and its attributes.
"""
attr_values = ", ".join(
f"{slot}={getattr(self, slot, None)}" for slot in self.__slots__
)
return f"({self.__class__.__name__}: {attr_values})"
[docs]
@abstractmethod
def accept(self, node_visitor: NodeVisitor):
"""
Abstract method to accept a visitor for traversing or processing the node.
:param node_visitor: NodeVisitor, which implements the specific visit method for this type of node.
:type node_visitor: NodeVisitor
:return: Depends on the NodeVisitor
"""
[docs]
@abstractmethod
def children(self):
"""
Returns a sequence of all child nodes.
:return: An iterable containing the child nodes of the current node.
"""
[docs]
class NodeVisitor(ABC):
"""
Base class for visiting AST nodes using the Visitor pattern.
This class defines a set of methods, one for each type of AST node,
which must be implemented by subclasses.
"""
[docs]
@abstractmethod
def visit_arraydecl(self, array_decl: ArrayDecl):
"""
Abstract method to visit an :class:`ArrayDecl` node.
Return depends on implementation of this method.
:param array_decl: The array declaration node.
:type array_decl: ArrayDecl
"""
[docs]
@abstractmethod
def visit_arrayref(self, array_ref: ArrayRef):
"""
Abstract method to visit an :class:`ArrayRef` node.
Return depends on implementation of this method.
:param array_ref: The array reference node.
:type array_ref: ArrayRef
"""
[docs]
@abstractmethod
def visit_assignment(self, assignment: Assignment):
"""
Abstract method to visit an :class:`Assignment` node.
Return depends on implementation of this method.
:param assignment: The assignment node.
:type assignment: Assignment
"""
[docs]
@abstractmethod
def visit_binaryop(self, binaryop: BinaryOp):
"""
Abstract method to visit a :class:`BinaryOp` node.
Return depends on implementation of this method.
:param binaryop: The binary operation node.
:type binaryop: BinaryOp
"""
[docs]
@abstractmethod
def visit_compound(self, compound: Compound):
"""
Abstract method to visit a :class:`Compound` node.
Return depends on implementation of this method.
:param compound: The compound node.
:type compound: Compound
"""
[docs]
@abstractmethod
def visit_compoundliteral(self, compound_literal: CompoundLiteral):
"""
Abstract method to visit a :class:`CompoundLiteral` node.
Return depends on implementation of this method.
:param compound_literal: The compound literal node.
:type compound_literal: CompoundLiteral
"""
[docs]
@abstractmethod
def visit_constant(self, constant: Constant):
"""
Abstract method to visit a :class:`Constant` node.
Return depends on implementation of this method.
:param constant: The constant node.
:type constant: Constant
"""
[docs]
@abstractmethod
def visit_decl(self, decl: Decl):
"""
Abstract method to visit a :class:`Decl` node.
Return depends on implementation of this method.
:param decl: The declaration node.
:type decl: Decl
"""
[docs]
@abstractmethod
def visit_decllist(self, decl_list: DeclList):
"""
Abstract method to visit a :class:`DeclList` node.
Return depends on implementation of this method.
:param decl_list: The declaration list node.
:type decl_list: DeclList
"""
[docs]
@abstractmethod
def visit_emptystatement(self):
"""
Abstract method to visit an :class:`EmptyStatement` node.
Return depends on implementation of this method.
"""
[docs]
@abstractmethod
def visit_exprlist(self, expr_list: ExprList):
"""
Abstract method to visit an :class:`ExprList` node.
Return depends on implementation of this method.
:param expr_list: The expression list node.
:type expr_list: ExprList
"""
[docs]
@abstractmethod
def visit_fileast(self, fileast: FileAST):
"""
Abstract method to visit a :class:`FileAST` node.
Return depends on implementation of this method.
:param fileast: The fileast node.
:type fileast: FileASt
"""
[docs]
@abstractmethod
def visit_funccall(self, funccall: FuncCall):
"""
Abstract method to visit a :class:`FuncCall` node.
Return depends on implementation of this method.
:param funccall: The function call node.
:type funccall: FuncCall
"""
[docs]
@abstractmethod
def visit_funcdecl(self, funcdecl: FuncDecl):
"""
Abstract method to visit a :class:`FuncDecl` node.
Return depends on implementation of this method.
:param funcdecl: The function declaration node.
:type funcdecl: FuncDecl
"""
[docs]
@abstractmethod
def visit_funcdef(self, funcdef: FuncDef):
"""
Abstract method to visit a :class:`FuncDef` node.
Return depends on implementation of this method.
:param funcdef: The function definition node.
:type funcdef: FuncDef
"""
[docs]
@abstractmethod
def visit_id(self, identifier: ID):
"""
Abstract method to visit an :class:`ID` node.
Return depends on implementation of this method.
:param identifier: The identifier node.
:type identifier: ID
"""
[docs]
@abstractmethod
def visit_identifiertype(self, identifier_type: IdentifierType):
"""
Abstract method to visit an :class:`IdentifierType` node.
Return depends on implementation of this method.
:param identifier_type: The identifier type node.
:type identifier_type: IdentifierType
"""
[docs]
@abstractmethod
def visit_initlist(self, init_list: InitList):
"""
Abstract method to visit an :class:`InitList` node.
Return depends on implementation of this method.
:param init_list: The initialization list node.
:type init_list: InitList
"""
[docs]
@abstractmethod
def visit_namedinitializer(self, named_initializer: NamedInitializer):
"""
Abstract method to visit a :class:`NamedInitializer` node.
Return depends on implementation of this method.
:param named_initializer: The named initializer node.
:type named_initializer: NamedInitializer
"""
[docs]
@abstractmethod
def visit_paramlist(self, param_list: ParamList):
"""
Abstract method to visit a :class:`ParamList` node.
Return depends on implementation of this method.
:param param_list: The parameter list node.
:type param_list: ParamList
"""
[docs]
@abstractmethod
def visit_rangedecl(self, range_decl: RangeDecl):
"""
Abstract method to visit a :class:`RangeDecl` node.
Return depends on implementation of this method.
:param range_decl: The range declaration node.
:type range_decl: RangeDecl
"""
[docs]
@abstractmethod
def visit_return(self, ret: Return):
"""
Abstract method to visit a :class:`Return` node.
Return depends on implementation of this method.
:param ret: The return node.
:type ret: Return
"""
[docs]
@abstractmethod
def visit_struct(self, struct: Struct):
"""
Abstract method to visit a :class:`Struct` node.
Return depends on implementation of this method.
:param struct: The struct node.
:type struct: Struct
"""
[docs]
@abstractmethod
def visit_structref(self, structref: StructRef):
"""
Abstract method to visit a :class:`StructRef` node.
Return depends on implementation of this method.
:param structref: The struct reference node.
:type structref: StructRef
"""
[docs]
@abstractmethod
def visit_typedecl(self, typedecl: TypeDecl):
"""
Abstract method to visit a :class:`TypeDecl` node.
Return depends on implementation of this method.
:param typedecl: The type declaration node.
:type typedecl: TypeDecl
"""
[docs]
@abstractmethod
def visit_typedef(self, typedef: Typedef):
"""
Abstract method to visit a :class:`Typedef` node.
Return depends on implementation of this method.
:param typedef: The type definition node.
:type typedef: Typedef
"""
[docs]
@abstractmethod
def visit_typename(self, typename: Typename):
"""
Abstract method to visit a :class:`Typename` node.
Return depends on implementation of this method.
:param typename: The type name node.
:type typename: Typename
"""
[docs]
@abstractmethod
def visit_unaryop(self, unaryop: UnaryOp):
"""
Abstract method to visit a :class:`UnaryOp` node.
Return depends on implementation of this method.
:param unaryop: The unary operation node.
:type unaryop: UnaryOp
"""
[docs]
class ArrayDecl(Node):
"""
Represents a nested declaration of an array with the given type.
:ivar type: The base type of the array.
:vartype type: Node
:ivar dim: The dimension (e.g., constant 42).
:vartype dim: int
:ivar dim_quals: List of dimension qualifiers, supporting C99's 'const' and 'static' in array dimensions.
:vartype dim_quals: list
"""
__slots__ = ("type", "dim", "dim_quals", "coord", "__weakref__")
def __init__(self, type, dim, dim_quals, coord = None):
self.type = type
self.dim = dim
self.dim_quals = dim_quals
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
if self.dim is not None:
nodelist.append(("dim", self.dim))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
if self.dim is not None:
yield self.dim
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_arraydecl(self)
attr_names = ('dim_quals',)
[docs]
class ArrayRef(Node):
"""
Represents an array reference in the AST.
:ivar name: The name of the array being referenced.
:vartype name: Node
:ivar subscript: The index or subscript of the array.
:vartype subscript: Node
"""
__slots__ = ('name', 'subscript', 'coord', '__weakref__')
def __init__(self, name, subscript, coord = None):
self.name = name
self.subscript = subscript
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.name is not None:
nodelist.append(("name", self.name))
if self.subscript is not None:
nodelist.append(("subscript", self.subscript))
return tuple(nodelist)
def __iter__(self):
if self.name is not None:
yield self.name
if self.subscript is not None:
yield self.subscript
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_arrayref(self)
attr_names = ()
[docs]
class Assignment(Node):
"""
Represents an assignment operation in the AST.
:ivar op: The assignment operator (e.g., "=", "+=").
:vartype op: str
:ivar lvalue: The left-hand side of the assignment.
:vartype lvalue: Node
:ivar rvalue: The right-hand side of the assignment.
:vartype rvalue: Node
"""
__slots__ = ("op", "lvalue", "rvalue", "coord", "__weakref__")
__annotations__ = {
"op": str,
"lvalue": Node,
"rvalue": Node,
"coord": Coord,
}
def __init__(self, op, lvalue, rvalue, coord = None):
self.op = op
self.lvalue = lvalue
self.rvalue = rvalue
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.lvalue is not None:
nodelist.append(("lvalue", self.lvalue))
if self.rvalue is not None:
nodelist.append(("rvalue", self.rvalue))
return tuple(nodelist)
def __iter__(self):
if self.lvalue is not None:
yield self.lvalue
if self.rvalue is not None:
yield self.rvalue
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_assignment(self)
attr_names = ("op",)
[docs]
class BinaryOp(Node):
"""
Represents a binary operation in the AST.
:ivar op: The binary operator (e.g., "+", "-", "*", "/").
:vartype op: str
:ivar left: The left operand of the binary operation.
:vartype left: Node
:ivar right: The right operand of the binary operation.
:vartype right: Node
"""
__slots__ = ("op", "left", "right", "coord", "__weakref__")
def __init__(self, op, left, right, coord = None):
self.op = op
self.left = left
self.right = right
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.left is not None:
nodelist.append(("left", self.left))
if self.right is not None:
nodelist.append(("right", self.right))
return tuple(nodelist)
def __iter__(self):
if self.left is not None:
yield self.left
if self.right is not None:
yield self.right
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_binaryop(self)
attr_names = ("op",)
[docs]
class Compound(Node):
"""
Represents a compound statement (block) in the AST.
:ivar block_items: A list of statements or declarations within the block.
:vartype block_items: list[Node]
"""
__slots__ = ("block_items", "coord", "__weakref__")
def __init__(self, block_items, coord = None):
self.block_items = block_items
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.block_items or []):
nodelist.append((f"block_items[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.block_items or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_compound(self)
attr_names = ()
[docs]
class CompoundLiteral(Node):
"""
Represents a compound literal (anonymous aggregate).
:ivar type: The type of the compound literal.
:vartype type: Node
:ivar init: The initializer for the compound literal.
:vartype init: Node
"""
__slots__ = ("type", "init", "coord", "__weakref__")
def __init__(self, type, init, coord = None):
self.type = type
self.init = init
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
if self.init is not None:
nodelist.append(("init", self.init))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
if self.init is not None:
yield self.init
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_compoundliteral(self)
attr_names = ()
[docs]
class Constant(Node):
"""
Represents a constant value in the AST.
:ivar type: The type of the constant (e.g., "int", "double", "char", "string").
:vartype type: str
:ivar value: The value of the constant.
:vartype value: str
"""
__slots__ = ("type", "value", "coord", "__weakref__")
def __init__(self, type, value, coord = None):
self.type = type
self.value = value
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
return tuple(nodelist)
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_constant(self)
attr_names = ('type', 'value',)
[docs]
class Decl(Node):
"""
Represents a variable or type declaration in the AST.
:ivar name: The name of the declared variable or type.
:vartype name: str
:ivar quals: A list of qualifiers (e.g., "const", "volatile").
:vartype quals: list[str]
:ivar type: The declaration type, possibly nested with modifiers.
:vartype type: Node
:ivar init: The initialization value, or None if not initialized.
:vartype init: Node
"""
__slots__ = ("name", "quals", "is_typedef", "funcspec",
"type", "init", "coord", "__weakref__")
def __init__(self, name, quals, is_typedef, funcspec,
type, init, coord = None):
self.name = name
self.quals = quals
self.is_typedef = is_typedef
self.funcspec = funcspec
self.type = type
self.init = init
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
if self.init is not None:
nodelist.append(("init", self.init))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
if self.init is not None:
yield self.init
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_decl(self)
attr_names = ("name", "quals", "is_typedef", "funcspec",)
[docs]
class DeclList(Node):
"""
Represents a list of declarations in the AST.
:ivar decls: A list of declarations.
:vartype decls: list[Node]
"""
__slots__ = ("decls", "coord", "__weakref__")
def __init__(self, decls, coord = None):
self.decls = decls
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.decls or []):
nodelist.append((f"decls[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.decls or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_decllist(self)
attr_names = ()
#
[docs]
class DoWhile(Node):
"""
Represents a do while loop in the AST.
NOT SUPPORTED BY NODEVISITOR!
"""
__slots__ = ("cond", "stmt", "coord", "__weakref__")
def __init__(self, cond, stmt, coord = None):
self.cond = cond
self.stmt = stmt
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.cond is not None:
nodelist.append(("cond", self.cond))
if self.stmt is not None:
nodelist.append(("stmt", self.stmt))
return tuple(nodelist)
def __iter__(self):
if self.cond is not None:
yield self.cond
if self.stmt is not None:
yield self.stmt
[docs]
def accept(self, node_visitor: NodeVisitor):
pass
attr_names = ()
[docs]
class EmptyStatement(Node):
"""
Represents an empty statement (a semicolon ";" on its own).
"""
__slots__ = ("coord", "__weakref__")
def __init__(self, coord = None):
self.coord = coord
super().__init__()
[docs]
def children(self):
return ()
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_emptystatement()
attr_names = ()
[docs]
class ExprList(Node):
"""
Represents a list of expressions separated by the comma operator.
:ivar exprs: A list of expressions.
:vartype exprs: list[Node]
"""
__slots__ = ("exprs", "coord", "__weakref__")
def __init__(self, exprs, coord = None):
self.exprs = exprs
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.exprs or []):
nodelist.append((f"exprs[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.exprs or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_exprlist(self)
attr_names = ()
[docs]
class FileAST(Node):
"""
Represents the top-level AST node for an UPPAAL file (a translation unit).
:ivar ext: A list of external declarations or definitions in the file.
:vartype ext: list[Node]
"""
__slots__ = ("ext", "coord", "__weakref__")
__annotations__ = {}
def __init__(self, ext, coord = None):
self.ext = ext
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.ext or []):
nodelist.append((f"ext[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.ext or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_fileast(self)
attr_names = ()
#
[docs]
class For(Node):
"""
Represents a for loop in the AST.
NOT SUPPORTED BY NODEVISITOR!
"""
__slots__ = ("init", "cond", "next", "stmt", "coord", "__weakref__")
def __init__(self, init, cond, next_, stmt, coord = None):
self.init = init
self.cond = cond
self.next = next_
self.stmt = stmt
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.init is not None:
nodelist.append(("init", self.init))
if self.cond is not None:
nodelist.append(("cond", self.cond))
if self.next is not None:
nodelist.append(("next", self.next))
if self.stmt is not None:
nodelist.append(("stmt", self.stmt))
return tuple(nodelist)
def __iter__(self):
if self.init is not None:
yield self.init
if self.cond is not None:
yield self.cond
if self.next is not None:
yield self.next
if self.stmt is not None:
yield self.stmt
[docs]
def accept(self, node_visitor: NodeVisitor):
pass
attr_names = ()
[docs]
class FuncCall(Node):
"""
Represents a function call in the AST.
:ivar name: The name of the function being called.
:vartype name: str
:ivar args: The arguments passed to the function.
:vartype args: Node
"""
__slots__ = ("name", "args", "coord", "__weakref__")
def __init__(self, name, args, coord = None):
self.name = name
self.args = args
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.name is not None:
nodelist.append(("name", self.name))
if self.args is not None:
nodelist.append(("args", self.args))
return tuple(nodelist)
def __iter__(self):
if self.name is not None:
yield self.name
if self.args is not None:
yield self.args
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_funccall(self)
attr_names = ()
[docs]
class FuncDecl(Node):
"""
Represents a function declaration in the AST.
:ivar args: The parameters of the function.
:vartype args: Node
:ivar type: The return type of the function.
:vartype type: Node
"""
__slots__ = ("args", "type", "coord", "__weakref__")
def __init__(self, args, type, coord = None):
self.args = args
self.type = type
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.args is not None:
nodelist.append(("args", self.args))
if self.type is not None:
nodelist.append(("type", self.type))
return tuple(nodelist)
def __iter__(self):
if self.args is not None:
yield self.args
if self.type is not None:
yield self.type
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_funcdecl(self)
attr_names = ()
[docs]
class FuncDef(Node):
"""
Represents a function definition in the AST.
:ivar decl: The declarator for the function name.
:vartype decl: Node
:ivar param_decls: A list of parameter declarations (optional, for K&R-style definitions).
:vartype param_decls: list[Node]
:ivar body: The body of the function (a compound statement).
:vartype body: Node
"""
__slots__ = ("decl", "param_decls", "body", "coord", "__weakref__")
def __init__(self, decl, param_decls, body, coord = None):
self.decl = decl
self.param_decls = param_decls
self.body = body
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.decl is not None:
nodelist.append(("decl", self.decl))
if self.body is not None:
nodelist.append(("body", self.body))
for i, child in enumerate(self.param_decls or []):
nodelist.append((f"param_decls[{i}]", child))
return tuple(nodelist)
def __iter__(self):
if self.decl is not None:
yield self.decl
if self.body is not None:
yield self.body
yield from (self.param_decls or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_funcdef(self)
attr_names = ()
[docs]
class ID(Node):
"""
Represents an identifier in the AST.
:ivar name: The name of the identifier.
:vartype name: str
"""
__slots__ = ("name", "coord", "__weakref__")
def __init__(self, name, coord = None):
self.name = name
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
return tuple(nodelist)
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_id(self)
attr_names = ("name",)
[docs]
class IdentifierType(Node):
"""
Represents a holder for types that are a simple identifier (e.g., built-in types like "int").
:ivar names: A list of type names (e.g., ["unsigned", "int"]).
:vartype names: list[str]
"""
__slots__ = ("names", "coord", "__weakref__")
def __init__(self, names, coord = None):
self.names = names
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
return tuple(nodelist)
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_identifiertype(self)
attr_names = ("names",)
#
[docs]
class If(Node):
"""
Represents an if statement in the AST.
NOT SUPPORTED BY NODEVISITOR!
"""
__slots__ = ('cond', 'iftrue', 'iffalse', 'coord', '__weakref__')
def __init__(self, cond, iftrue, iffalse, coord = None):
self.cond = cond
self.iftrue = iftrue
self.iffalse = iffalse
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.cond is not None:
nodelist.append(("cond", self.cond))
if self.iftrue is not None:
nodelist.append(("iftrue", self.iftrue))
if self.iffalse is not None:
nodelist.append(("iffalse", self.iffalse))
return tuple(nodelist)
def __iter__(self):
if self.cond is not None:
yield self.cond
if self.iftrue is not None:
yield self.iftrue
if self.iffalse is not None:
yield self.iffalse
[docs]
def accept(self, node_visitor: NodeVisitor):
pass
attr_names = ()
[docs]
class InitList(Node):
"""
Represents an initialization list used for compound literals.
:ivar exprs: A list of expressions for initialization.
:vartype exprs: list[Node]
"""
__slots__ = ("exprs", "coord", "__weakref__")
def __init__(self, exprs, coord = None):
self.exprs = exprs
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.exprs or []):
nodelist.append((f"exprs[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.exprs or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_initlist(self)
attr_names = ()
[docs]
class NamedInitializer(Node):
"""
Represents a named initializer for C99.
:ivar name: A sequence of nodes representing the name (e.g., hierarchical or constant expressions).
:vartype name: list[Node]
:ivar expr: The expression initializing the name.
:vartype expr: Node
"""
__slots__ = ("name", "expr", "coord", "__weakref__")
def __init__(self, name, expr, coord = None):
self.name = name
self.expr = expr
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.expr is not None:
nodelist.append(("expr", self.expr))
for i, child in enumerate(self.name or []):
nodelist.append((f"name[{i}]", child))
return tuple(nodelist)
def __iter__(self):
if self.expr is not None:
yield self.expr
yield from (self.name or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_namedinitializer(self)
attr_names = ()
[docs]
class ParamList(Node):
"""
Represents a list of function parameter declarations.
:ivar params: A list of parameter declarations.
:vartype params: list[Node]
"""
__slots__ = ("params", "coord", "__weakref__")
def __init__(self, params, coord = None):
self.params = params
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.params or []):
nodelist.append((f"params[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.params or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_paramlist(self)
attr_names = ()
[docs]
class RangeDecl(Node):
"""
Represents an UPPAAL range declaration.
:ivar type: The range type, possibly nested with modifiers.
:vartype type: Node
:ivar lower: The lower bound of the range (integer or ID).
:vartype lower: Node
:ivar upper: The upper bound of the range (integer or ID).
:vartype upper: Node
"""
__slots__ = ("type", "lower", "upper", "coord", "__weakref__")
def __init__(self, type, lower, upper, coord = None):
self.type = type
self.lower = lower
self.upper = upper
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
if self.lower is not None:
nodelist.append(("lower", self.lower))
if self.upper is not None:
nodelist.append(("upper", self.upper))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_rangedecl(self)
attr_names = ()
[docs]
class Return(Node):
"""
Represents a return statement in the AST.
:ivar expr: The expression being returned, or None if it's a void return.
:vartype expr: Node or None
"""
__slots__ = ("expr", "coord", "__weakref__")
def __init__(self, expr, coord = None):
self.expr = expr
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.expr is not None:
nodelist.append(("expr", self.expr))
return tuple(nodelist)
def __iter__(self):
if self.expr is not None:
yield self.expr
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_return(self)
attr_names = ()
[docs]
class Struct(Node):
"""
Represents a struct declaration in the AST.
:ivar name: The tag name of the struct.
:vartype name: str
:ivar decls: The declarations of members in the struct.
:vartype decls: list[Node]
"""
__slots__ = ("name", "decls", "coord", "__weakref__")
def __init__(self, name, decls, coord = None):
self.name = name
self.decls = decls
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
for i, child in enumerate(self.decls or []):
nodelist.append((f"decls[{i}]", child))
return tuple(nodelist)
def __iter__(self):
yield from (self.decls or [])
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_struct(self)
attr_names = ("name",)
[docs]
class StructRef(Node):
"""
Represents a reference to a struct field.
:ivar name: The struct being referenced.
:vartype name: Node
:ivar type: The type of reference ("." for member access or "->" for pointer dereference).
:vartype type: str
:ivar field: The field being accessed in the struct.
:vartype field: Node
"""
__slots__ = ("name", "type", "field", "coord", "__weakref__")
def __init__(self, name, type, field, coord = None):
self.name = name
self.type = type
self.field = field
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.name is not None:
nodelist.append(("name", self.name))
if self.field is not None:
nodelist.append(("field", self.field))
return tuple(nodelist)
def __iter__(self):
if self.name is not None:
yield self.name
if self.field is not None:
yield self.field
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_structref(self)
attr_names = ("type",)
[docs]
class TypeDecl(Node):
"""
Represents a base type declaration in the AST.
:ivar declname: The name of the declaration.
:vartype declname: str
:ivar quals: A list of qualifiers (e.g., "const", "volatile").
:vartype quals: list[str]
:ivar type: The type of the declaration.
:vartype type: Node
"""
__slots__ = ("declname", "quals", "type", "coord", "__weakref__")
def __init__(self, declname, quals, type, coord = None):
self.declname = declname
self.quals = quals
self.type = type
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_typedecl(self)
attr_names = ("declname", "quals",)
[docs]
class Typedef(Node):
"""
Represents a typedef declaration in the AST.
:ivar name: The name of the typedef.
:vartype name: str
:ivar quals: A list of qualifiers (e.g., "const", "volatile").
:vartype quals: list[str]
:ivar is_typedef: The is_typedef flag.
:vartype is_typedef: bool
:ivar type: The type being defined by the typedef.
:vartype type: Node
"""
__slots__ = ("name", "quals", "is_typedef", "type", "coord", "__weakref__")
def __init__(self, name, quals, is_typedef, type, coord = None):
self.name = name
self.quals = quals
self.is_typedef = is_typedef
self.type = type
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_typedef(self)
attr_names = ("name", "quals", "is_typedef",)
[docs]
class Typename(Node):
"""
Represents a typename in the AST.
:ivar name: The name of the typename (or None for unnamed types).
:vartype name: str or None
:ivar quals: A list of qualifiers (e.g., "const", "volatile").
:vartype quals: list[str]
:ivar type: The type being referred to by the typename.
:vartype type: Node
"""
__slots__ = ("name", "quals", "type", "coord", "__weakref__")
def __init__(self, name, quals, type, coord = None):
self.name = name
self.quals = quals
self.type = type
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.type is not None:
nodelist.append(("type", self.type))
return tuple(nodelist)
def __iter__(self):
if self.type is not None:
yield self.type
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_typename(self)
attr_names = ("name", "quals",)
[docs]
class UnaryOp(Node):
"""
Represents a unary operation in the AST.
:ivar op: The unary operator (e.g., "-", "!", "~").
:vartype op: str
:ivar expr: The operand of the unary operation.
:vartype expr: Node
"""
__slots__ = ("op", "expr", "coord", "__weakref__")
def __init__(self, op, expr, coord = None):
self.op = op
self.expr = expr
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.expr is not None:
nodelist.append(("expr", self.expr))
return tuple(nodelist)
def __iter__(self):
if self.expr is not None:
yield self.expr
[docs]
def accept(self, node_visitor: NodeVisitor):
return node_visitor.visit_unaryop(self)
attr_names = ("op",)
#
[docs]
class While(Node):
"""
Represents a while loop in the AST.
NOT SUPPORTED BY NODEVISITOR!
"""
__slots__ = ('cond', 'stmt', 'coord', '__weakref__')
def __init__(self, cond, stmt, coord = None):
self.cond = cond
self.stmt = stmt
self.coord = coord
super().__init__()
[docs]
def children(self):
nodelist = []
if self.cond is not None:
nodelist.append(("cond", self.cond))
if self.stmt is not None:
nodelist.append(("stmt", self.stmt))
return tuple(nodelist)
def __iter__(self):
if self.cond is not None:
yield self.cond
if self.stmt is not None:
yield self.stmt
[docs]
def accept(self, node_visitor: NodeVisitor):
pass
attr_names = ()