Source code for cnorm.nodes

from pyrser import parsing, meta

Storages = meta.enum('AUTO', 'REGISTER', 'TYPEDEF',
                     'STATIC', 'EXTERN', 'INLINE',
                     'VIRTUAL', 'EXPLICIT',
                     'FORCEINLINE', 'THREAD')
Qualifiers = meta.enum('AUTO', 'CONST', 'VOLATILE', 'RESTRICT',
                       'W64', 'STDCALL', 'CDECL',
                       'PTR32', 'PTR64', 'FASTCALL')
Specifiers = meta.enum('AUTO', 'STRUCT', 'UNION', 'ENUM', 'LONG',
                       'LONGLONG', 'SHORT')
Signs = meta.enum('AUTO', 'SIGNED', 'UNSIGNED')

# EXPRESSION PART


[docs]class Expr(parsing.Node): """All expression"""
[docs]class Func(Expr): """For almost everything"""
[docs] def __init__(self, call_expr: Expr, params: list): Expr.__init__(self) self.call_expr = call_expr self.params = params
[docs]class BlockInit(Expr): """Initializer Block Expression"""
[docs] def __init__(self, body: [Expr]): self.body = body
[docs]class BlockExpr(Expr): """Compound Block Expression"""
[docs] def __init__(self, body: [Expr]): self.body = body
[docs]class Unary(Func): """For unary operator"""
[docs]class Paren(Unary): """For () expression"""
[docs]class Array(Unary): """For [] expression"""
[docs]class Dot(Unary): """For . expression"""
[docs]class Arrow(Unary): """For -> expression"""
[docs]class Post(Unary): """For post{inc,dec} expression"""
[docs]class Sizeof(Unary): """For sizeof expr/type expression"""
[docs]class Binary(Func): """For binary operator"""
[docs]class Cast(Binary): """For cast operator"""
[docs]class Range(Binary): """For range expression"""
[docs]class Ternary(Func): """For ternary operator"""
[docs]class Terminal(Expr): """For Terminal expression"""
[docs] def __init__(self, value: str): Expr.__init__(self) self.value = value
[docs]class Id(Terminal): """Terminal Id"""
[docs]class Literal(Terminal): """Terminal Literal"""
[docs]class Raw(Terminal): """Terminal Raw""" # DECLARATION PART
[docs]class Enumerator(parsing.Node): """Enumerator A=x in enums"""
[docs] def __init__(self, ident: str, expr: Expr): self.ident = ident self.expr = expr
[docs]class DeclType(parsing.Node): """For type in declaration"""
[docs] def __init__(self): self._decltype = None
[docs] def push(self, t: 'DeclType'=None): if t is not None: if not isinstance(t, DeclType): raise Exception("add only C type declarator") old = self._decltype self._decltype = t self._decltype.link(old) return self._decltype
[docs]class PointerType(DeclType): """For pointer in declaration"""
[docs]class ArrayType(DeclType): """For array in declaration"""
[docs] def __init__(self, expr=None): DeclType.__init__(self) self._expr = expr
@property def expr(self): return self._expr
[docs]class ParenType(DeclType): """For parenthesis in declaration"""
[docs] def __init__(self, params=None): DeclType.__init__(self) if params is None: params = [] self._params = params
@property def params(self): return self._params
[docs]class QualType(DeclType): """For qualifier in declaration"""
[docs] def __init__(self, qualifier: Qualifiers=Qualifiers.AUTO): DeclType.__init__(self) # qualifier in (auto, const, volatile, restrict) self._qualifier = qualifier
[docs]class AttrType(DeclType): """For attribute specifier in declaration"""
[docs] def __init__(self, raw: str): DeclType.__init__(self) # fix self._attr = raw.rstrip(' ')
[docs]class CType(parsing.Node): """Base for primary/func"""
[docs] def __init__(self): parsing.Node.__init__(self) self._decltype = None # only one storage by declaration # i.e: auto, register, typedef, static, extern, ... self._storage = Storages.AUTO # only one specifier by declaration # i.e: auto, short, long, struct, union, enum, ... self._specifier = Specifiers.AUTO
[docs] def copy(self): import copy theclone = copy.copy(self) theclone._decltype = None return theclone
[docs] def push(self, t: DeclType=None): if t is not None: if not isinstance(t, DeclType): raise Exception("add only C type declarator") old = self._decltype self._decltype = t self._decltype.link(old) return self._decltype
[docs]class PrimaryType(CType): """For primary type in declaration"""
[docs] def __init__(self, identifier: str): CType.__init__(self) # identifier (void, char, int, float, double, typedefname) self._identifier = identifier
@property def identifier(self): return self._identifier
[docs]class ComposedType(CType): """For composed type in declaration"""
[docs] def __init__(self, identifier: str): CType.__init__(self) # identifier (name of the struct/union/enum) self._identifier = identifier # if struct/union then self.fields = [] # if enum then self.enums = []
@property def identifier(self): return self._identifier
[docs]class FuncType(PrimaryType): """For function in declaration"""
[docs] def __init__(self, identifier: str, params=[], decltype=None): PrimaryType.__init__(self, identifier) self.opened = True if decltype is not None: self._decltype = decltype self._params = params
@property def params(self): return self._params # helper to create a CType from previous one
[docs]def makeCType(declspecifier: str, ctype=None): from cnorm.parsing.expression import Idset if ctype is None: ctype = PrimaryType('int') if Idset[declspecifier] == "type": ctype._identifier = declspecifier if Idset[declspecifier] == "storage": cleantxt = declspecifier.strip("_") ctype._storage = Storages.map[cleantxt.upper()] if Idset[declspecifier] == "qualifier": cleantxt = declspecifier.strip("_") ctype.link(QualType(Qualifiers.map[cleantxt.upper()])) if Idset[declspecifier] == "funspecifier": cleantxt = declspecifier.strip("_") ctype._storage = Storages.map[cleantxt.upper()] if Idset[declspecifier] == "sign_unsigned": cleantxt = declspecifier.strip("_") ctype._sign = Signs.map[cleantxt.upper()] if Idset[declspecifier] == "sign_signed": cleantxt = declspecifier.strip("_") ctype._sign = Signs.map[cleantxt.upper()] if Idset[declspecifier] == "specifier_block": cleantxt = declspecifier.strip("_") ctype._specifier = Specifiers.map[cleantxt.upper()] if Idset[declspecifier] == "specifier_enum": cleantxt = declspecifier.strip("_") ctype._specifier = Specifiers.map[cleantxt.upper()] if Idset[declspecifier] == "specifier_size": cleantxt = declspecifier.strip("_") ctype._specifier = Specifiers.map[cleantxt.upper()] if Idset[declspecifier] == "specifier_size_size": cleantxt = declspecifier.strip("_") if ctype._specifier == Specifiers.AUTO: ctype._specifier = Specifiers.map[cleantxt.upper()] else: ctype._specifier = Specifiers.LONGLONG return ctype
[docs]class Decl(Expr): """For basic declaration A declaration contains the following attributes: * _name: name of the declaration * _ctype: the CType describing the type of the declaration * _assign_expr: when the declaration have a value * _colon_expr: When it's a bitfield * body: when it's function definition """
[docs] def __init__(self, name: str, ct=None): if ct is None: ct = PrimaryType('int') Expr.__init__(self) self._name = name self._ctype = ct
@property def ctype(self) -> CType: return self._ctype
[docs] def assign_expr(self, expr=None): if not hasattr(self, '_assign_expr'): self._assign_expr = None if expr is not None: self._assign_expr = expr return self._assign_expr
[docs] def colon_expr(self, expr=None): if not hasattr(self, '_colon_expr'): self._colon_expr = None if expr is not None: self._colon_expr = expr return self._colon_expr # STATEMENT PART
[docs]class Stmt(parsing.Node): """For statement"""
[docs]class ExprStmt(Stmt): """Expression statement"""
[docs] def __init__(self, expr: Expr): parsing.Node.__init__(self) self.expr = expr
[docs]class BlockStmt(Stmt): """Block statement"""
[docs] def __init__(self, body: [ExprStmt]): parsing.Node.__init__(self) self.body = body
[docs] def func(self, name: str): """return the first func defined named name""" for f in self.body: if (hasattr(f, '_ctype') and isinstance(f._ctype, FuncType) and f._name == name): return f
[docs] def var(self, name: str): """return the first var instancied named name""" for f in self.body: if (hasattr(f, '_ctype') and not isinstance(f._ctype, FuncType) and f._name == name): return f
[docs] def type(self, name: str): """return the first complete definition of type 'name'""" for f in self.body: if (hasattr(f, '_ctype') and f._ctype._storage == Storages.TYPEDEF and f._name == name): return f
[docs] def declfuncs(self, name: str): """generator on all declaration of function 'name'""" for f in self.body: if (hasattr(f, '_ctype') and isinstance(f._ctype, FuncType) and f._name == name): yield f
[docs] def declvars(self, name: str): """generator on all declaration of variable 'name'""" for f in self.body: if (hasattr(f, '_ctype') and not isinstance(f._ctype, FuncType) and f._name == name): yield f
[docs] def decltypes(self, name: str): """generator on all declaration of type 'name'""" for f in self.body: if (hasattr(f, '_ctype') and f._ctype._storage == Storages.TYPEDEF and f._name == name): yield f
[docs] def declallfuncs(self): """generator on all declaration of function""" for f in self.body: if (hasattr(f, '_ctype') and isinstance(f._ctype, FuncType)): yield f
[docs] def declallvars(self): """generator on all declaration of variable""" for f in self.body: if (hasattr(f, '_ctype') and not isinstance(f._ctype, FuncType)): yield f
[docs] def declalltypes(self): """generator on all declaration of type""" for f in self.body: if (hasattr(f, '_ctype') and f._ctype._storage == Storages.TYPEDEF): yield f
[docs]class RootBlockStmt(BlockStmt): """Root Block statement"""
[docs] def __init__(self, body: [ExprStmt]): BlockStmt.__init__(self, body) from collections import ChainMap self.types = ChainMap()
[docs]class Label(Stmt): """Label statement"""
[docs] def __init__(self, value: str): Stmt.__init__(self) self.value = value
[docs]class Branch(Label): """branch statement"""
[docs] def __init__(self, value: str, expr: Expr): Label.__init__(self, value) self.expr = expr
[docs]class Case(Branch): """Case statement"""
[docs] def __init__(self, expr: Expr): Branch.__init__(self, "case", expr)
[docs]class Return(Branch): """Return statement"""
[docs] def __init__(self, expr: Expr): Branch.__init__(self, "return", expr)
[docs]class Goto(Branch): """Goto statement"""
[docs] def __init__(self, expr: Expr): Branch.__init__(self, "goto", expr)
[docs]class LoopControl(Label): """loop control statement"""
[docs]class Break(LoopControl): """break statement"""
[docs] def __init__(self): Label.__init__(self, "break")
[docs]class Continue(LoopControl): """continue statement"""
[docs] def __init__(self): Label.__init__(self, "continue")
[docs]class Conditional(Stmt): """Conditional statement"""
[docs] def __init__(self, condition: Expr): Stmt.__init__(self) self.condition = condition
[docs]class If(Conditional): """If statement"""
[docs] def __init__(self, condition: Expr, thencond: Stmt, elsecond: Stmt=None): Conditional.__init__(self, condition) self.thencond = thencond self.elsecond = elsecond
[docs]class While(Conditional): """While statement"""
[docs] def __init__(self, condition: Expr, body: Stmt): Conditional.__init__(self, condition) self.body = body
[docs]class Switch(Conditional): """Switch statement"""
[docs] def __init__(self, condition: Expr, body: Stmt): Conditional.__init__(self, condition) self.body = body
[docs]class Do(Conditional): """Do statement"""
[docs] def __init__(self, condition: Expr, body: Stmt): Conditional.__init__(self, condition) self.body = body
[docs]class For(Stmt): """For statement"""
[docs] def __init__(self, init: Expr, condition: Expr, increment: Expr, body: Stmt): Stmt.__init__(self) self.init = init self.condition = condition self.increment = increment self.body = body