"""Declarations Tree Visitor
This file provides a Visitor to traverse an AST and return a string representation of the node
structure for debugging purposes.
This file can be imported and contains the following classes:
* DeclarationsTreeVisitor: NodeVisitor that traverses the declarations and returns a string.
"""
from uppaal2jetracer.declarations.declarations_ast import NodeVisitor, ArrayDecl, ArrayRef, \
Assignment, BinaryOp, Compound, CompoundLiteral, Constant, Decl, DeclList, \
ExprList, FileAST, FuncCall, FuncDecl, FuncDef, ID, IdentifierType, InitList, \
NamedInitializer, ParamList, Return, Struct, StructRef, TypeDecl, Typedef, Typename, UnaryOp, \
RangeDecl
[docs]
class DeclarationsTreeVisitor(NodeVisitor):
"""
Declarations Tree Visitor
An implementation of the class:`NodeVisitor`. It returns a string representation
of the AST's node structure for debugging purposes.
"""
[docs]
def visit_arraydecl(self, array_decl: ArrayDecl):
return f"(ArrayDecl: {array_decl.type.accept(self)})"
[docs]
def visit_arrayref(self, array_ref: ArrayRef):
return f"(ArrayRef: {array_ref.name}[{array_ref.subscript.accept(self)}])"
[docs]
def visit_assignment(self, assignment: Assignment):
lvalue = assignment.lvalue.accept(self)
rvalue = assignment.rvalue.accept(self)
return f"(Assignment: {lvalue} {assignment.op} ({rvalue}))"
[docs]
def visit_binaryop(self, binaryop: BinaryOp):
lvalue = binaryop.left.accept(self)
rvalue = binaryop.right.accept(self)
return f"(BinaryOp: ({lvalue}) {binaryop.op} ({rvalue}))"
[docs]
def visit_compound(self, compound: Compound):
if compound.block_items is None:
return ""
return (f"(Compound: "
f"{", ".join(block_item.accept(self) for block_item in compound.block_items)})")
[docs]
def visit_compoundliteral(self, compound_literal: CompoundLiteral):
return (f"(CompoundLiteral: ({compound_literal.type.accept(self)})"
f"({compound_literal.init.accept(self)}))")
[docs]
def visit_constant(self, constant: Constant):
return f"(Constant: {constant.value})"
[docs]
def visit_decl(self, decl: Decl):
func_spec = f"{" ".join(decl.funcspec)} " if decl.funcspec else ""
is_typedef = "typedef " if decl.is_typedef else ""
dtype = decl.type.accept(self)
init = f" = {decl.init.accept(self)}" if decl.init else ""
return f"(Decl: {func_spec}{is_typedef}{dtype}{init})"
[docs]
def visit_decllist(self, decl_list: DeclList):
return (f"(DeclList: "
f"{", ".join(declaration.accept(self) for declaration in decl_list.decls)})")
[docs]
def visit_emptystatement(self):
return "(EmptyStatement)"
[docs]
def visit_exprlist(self, expr_list: ExprList):
return f"(ExprList: {", ".join(expr.accept(self) for expr in expr_list.exprs)})"
[docs]
def visit_fileast(self, fileast: FileAST):
return f"(FileAST: {", ".join(ext.accept(self) for ext in fileast.ext)})"
[docs]
def visit_funccall(self, funccall: FuncCall):
return (f"(FuncCall: {funccall.name.accept(self)}"
f"({funccall.args.accept(self) if funccall.args else ''}))")
[docs]
def visit_funcdecl(self, funcdecl: FuncDecl):
return f"(FuncDecl: {funcdecl.type.accept(self)})"
[docs]
def visit_funcdef(self, funcdef: FuncDef):
decl = funcdef.decl.accept(self)
body = funcdef.body.accept(self)
# K&R declaration style omitted
return f"(FuncDef: {decl}({body}))"
[docs]
def visit_id(self, identifier: ID):
return f"(ID: {identifier.name})"
[docs]
def visit_identifiertype(self, identifier_type: IdentifierType):
return f"(IdentifierType: {" ".join(identifier_type.names)})"
[docs]
def visit_initlist(self, init_list: InitList):
return f"(InitList: {", ".join(expr.accept(self) for expr in init_list.exprs)})"
[docs]
def visit_namedinitializer(self, named_initializer: NamedInitializer):
initializers = ""
for name in named_initializer.name:
if isinstance(name, ID):
initializers += f".{name.name}"
else:
initializers += f"[{name.accept(self)}]"
return f"(NamedInitializer: {initializers} = {named_initializer.expr.accept(self)})"
[docs]
def visit_paramlist(self, param_list: ParamList):
return f"(ParamList: {", ".join(param.accept(self) for param in param_list.params)})"
[docs]
def visit_rangedecl(self, range_decl: RangeDecl):
return (f"(RangeDecl: {range_decl.type.accept(self)} "
f"[{range_decl.lower.accept(self)}, {range_decl.upper.accept(self)}])")
[docs]
def visit_return(self, ret: Return):
return f"(Return: {ret.expr.accept(self) if ret.expr else ""})"
[docs]
def visit_struct(self, struct: Struct):
members = struct.decls
s = f"Struct: {struct.name}"
if members is not None:
s += f" ({"".join(decl.accept(self) for decl in members)})"
return f"({s})"
[docs]
def visit_structref(self, structref: StructRef):
return f"(StructRef: {structref.name} {structref.type} {structref.field.accept(self)})"
[docs]
def visit_typedecl(self, typedecl: TypeDecl):
s = "TypeDecl: "
# Qualifiers
if typedecl.quals:
s += f"{"".join(typedecl.quals)} "
s += typedecl.type.accept(self)
# nstr heißt in diesem Kontext typedecl_str
# Resolve modifiers.
# Wrap in parens to distinguish pointer to array and pointer to
# function syntax.
# #
# for i, modifier in enumerate(modifiers):
#
# if isinstance(modifier, c_ast.ArrayDecl): #
#
# if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
# nstr = '(' + nstr + ')'
#
# nstr += '['
#
# if modifier.dim_quals:
# nstr += ' '.join(modifier.dim_quals) + ' '
#
# nstr += self.visit(modifier.dim) + ']'
#
# elif isinstance(modifier, c_ast.FuncDecl):
# if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
# nstr = '(' + nstr + ')'
# nstr += '(' + self.visit(modifier.args) + ')'
#
# elif isinstance(modifier, c_ast.PtrDecl):
# if modifier.quals:
# nstr = '* %s%s' % (' '.join(modifier.quals),
# ' ' + nstr if nstr else '')
# else:
# nstr = '*' + nstr
if typedecl.declname:
s += f" {typedecl.declname}"
return f"({s})"
[docs]
def visit_typedef(self, typedef: Typedef):
return f"(Typedef: is_typedef={typedef.is_typedef} {typedef.type.accept(self)})"
[docs]
def visit_typename(self, typename: Typename):
return f"(Typename: {typename.type.accept(self)})"
[docs]
def visit_unaryop(self, unaryop: UnaryOp):
operand = unaryop.expr.accept(self)
if unaryop.op == 'p++':
return f"(UnaryOp: {operand}++)"
if unaryop.op == 'p--':
return f"(UnaryOp: {operand}--)"
return f"(UnaryOp: {unaryop.op}{operand})"