1# ---------------------------------------------------------------------- 2# phpast.py 3# 4# PHP abstract syntax node definitions. 5# ---------------------------------------------------------------------- 6 7class Node(object): 8 fields = [] 9 10 def __init__(self, *args, **kwargs): 11 assert len(self.fields) == len(args), \ 12 '%s takes %d arguments' % (self.__class__.__name__, 13 len(self.fields)) 14 try: 15 self.lineno = kwargs['lineno'] 16 except KeyError: 17 self.lineno = None 18 for i, field in enumerate(self.fields): 19 setattr(self, field, args[i]) 20 21 def __repr__(self): 22 return "%s(%s)" % (self.__class__.__name__, 23 ', '.join([repr(getattr(self, field)) 24 for field in self.fields])) 25 26 def __eq__(self, other): 27 if not isinstance(other, self.__class__): 28 return False 29 for field in self.fields: 30 if not (getattr(self, field) == getattr(other, field)): 31 return False 32 return True 33 34 def accept(self, visitor): 35 visitor(self) 36 for field in self.fields: 37 value = getattr(self, field) 38 if isinstance(value, Node): 39 value.accept(visitor) 40 elif isinstance(value, list): 41 for item in value: 42 if isinstance(item, Node): 43 item.accept(visitor) 44 45 def generic(self, with_lineno=False): 46 values = {} 47 if with_lineno: 48 values['lineno'] = self.lineno 49 for field in self.fields: 50 value = getattr(self, field) 51 if hasattr(value, 'generic'): 52 value = value.generic(with_lineno) 53 elif isinstance(value, list): 54 items = value 55 value = [] 56 for item in items: 57 if hasattr(item, 'generic'): 58 item = item.generic(with_lineno) 59 value.append(item) 60 values[field] = value 61 return (self.__class__.__name__, values) 62 63def node(name, fields): 64 attrs = {'fields': fields} 65 return type(name, (Node,), attrs) 66 67InlineHTML = node('InlineHTML', ['data']) 68Block = node('Block', ['nodes']) 69Assignment = node('Assignment', ['node', 'expr', 'is_ref']) 70ListAssignment = node('ListAssignment', ['nodes', 'expr']) 71New = node('New', ['name', 'params']) 72Clone = node('Clone', ['node']) 73Break = node('Break', ['node']) 74Continue = node('Continue', ['node']) 75Return = node('Return', ['node']) 76Yield = node('Yield', ['node']) 77Global = node('Global', ['nodes']) 78Static = node('Static', ['nodes']) 79Echo = node('Echo', ['nodes']) 80Print = node('Print', ['node']) 81Unset = node('Unset', ['nodes']) 82Try = node('Try', ['nodes', 'catches', 'finally']) 83Catch = node('Catch', ['class_', 'var', 'nodes']) 84Finally = node('Finally', ['nodes']) 85Throw = node('Throw', ['node']) 86Declare = node('Declare', ['directives', 'node']) 87Directive = node('Directive', ['name', 'node']) 88Function = node('Function', ['name', 'params', 'nodes', 'is_ref']) 89Method = node('Method', ['name', 'modifiers', 'params', 'nodes', 'is_ref']) 90Closure = node('Closure', ['params', 'vars', 'nodes', 'is_ref']) 91Class = node('Class', ['name', 'type', 'extends', 'implements', 'traits', 'nodes']) 92Trait = node('Trait', ['name', 'traits', 'nodes']) 93ClassConstants = node('ClassConstants', ['nodes']) 94ClassConstant = node('ClassConstant', ['name', 'initial']) 95ClassVariables = node('ClassVariables', ['modifiers', 'nodes']) 96ClassVariable = node('ClassVariable', ['name', 'initial']) 97Interface = node('Interface', ['name', 'extends', 'nodes']) 98AssignOp = node('AssignOp', ['op', 'left', 'right']) 99BinaryOp = node('BinaryOp', ['op', 'left', 'right']) 100UnaryOp = node('UnaryOp', ['op', 'expr']) 101TernaryOp = node('TernaryOp', ['expr', 'iftrue', 'iffalse']) 102PreIncDecOp = node('PreIncDecOp', ['op', 'expr']) 103PostIncDecOp = node('PostIncDecOp', ['op', 'expr']) 104Cast = node('Cast', ['type', 'expr']) 105IsSet = node('IsSet', ['nodes']) 106Empty = node('Empty', ['expr']) 107Eval = node('Eval', ['expr']) 108Include = node('Include', ['expr', 'once']) 109Require = node('Require', ['expr', 'once']) 110Exit = node('Exit', ['expr', 'type']) 111Silence = node('Silence', ['expr']) 112MagicConstant = node('MagicConstant', ['name', 'value']) 113Constant = node('Constant', ['name']) 114Variable = node('Variable', ['name']) 115StaticVariable = node('StaticVariable', ['name', 'initial']) 116LexicalVariable = node('LexicalVariable', ['name', 'is_ref']) 117FormalParameter = node('FormalParameter', ['name', 'default', 'is_ref', 'type']) 118Parameter = node('Parameter', ['node', 'is_ref']) 119FunctionCall = node('FunctionCall', ['name', 'params']) 120Array = node('Array', ['nodes']) 121ArrayElement = node('ArrayElement', ['key', 'value', 'is_ref']) 122ArrayOffset = node('ArrayOffset', ['node', 'expr']) 123StringOffset = node('StringOffset', ['node', 'expr']) 124ObjectProperty = node('ObjectProperty', ['node', 'name']) 125StaticProperty = node('StaticProperty', ['node', 'name']) 126MethodCall = node('MethodCall', ['node', 'name', 'params']) 127StaticMethodCall = node('StaticMethodCall', ['class_', 'name', 'params']) 128If = node('If', ['expr', 'node', 'elseifs', 'else_']) 129ElseIf = node('ElseIf', ['expr', 'node']) 130Else = node('Else', ['node']) 131While = node('While', ['expr', 'node']) 132DoWhile = node('DoWhile', ['node', 'expr']) 133For = node('For', ['start', 'test', 'count', 'node']) 134Foreach = node('Foreach', ['expr', 'keyvar', 'valvar', 'node']) 135ForeachVariable = node('ForeachVariable', ['name', 'is_ref']) 136Switch = node('Switch', ['expr', 'nodes']) 137Case = node('Case', ['expr', 'nodes']) 138Default = node('Default', ['nodes']) 139Namespace = node('Namespace', ['name', 'nodes']) 140UseDeclarations = node('UseDeclarations', ['nodes']) 141UseDeclaration = node('UseDeclaration', ['name', 'alias']) 142ConstantDeclarations = node('ConstantDeclarations', ['nodes']) 143ConstantDeclaration = node('ConstantDeclaration', ['name', 'initial']) 144TraitUse = node('TraitUse', ['name', 'renames']) 145TraitModifier = node('TraitModifier', ['from', 'to', 'visibility']) 146 147def resolve_magic_constants(nodes): 148 current = {} 149 def visitor(node): 150 if isinstance(node, Namespace): 151 current['namespace'] = node.name 152 elif isinstance(node, Class): 153 current['class'] = node.name 154 elif isinstance(node, Function): 155 current['function'] = node.name 156 elif isinstance(node, Method): 157 current['method'] = node.name 158 elif isinstance(node, MagicConstant): 159 if node.name == '__NAMESPACE__': 160 node.value = current.get('namespace') 161 elif node.name == '__CLASS__': 162 node.value = current.get('class') 163 if current.get('namespace'): 164 node.value = '%s\\%s' % (current.get('namespace'), 165 node.value) 166 elif node.name == '__FUNCTION__': 167 node.value = current.get('function') 168 if current.get('namespace'): 169 node.value = '%s\\%s' % (current.get('namespace'), 170 node.value) 171 elif node.name == '__METHOD__': 172 node.value = current.get('method') 173 if current.get('class'): 174 node.value = '%s::%s' % (current.get('class'), 175 node.value) 176 if current.get('namespace'): 177 node.value = '%s\\%s' % (current.get('namespace'), 178 node.value) 179 for node in nodes: 180 if isinstance(node, Node): 181 node.accept(visitor) 182