113481Sgiacomo.travaglini@arm.com#!/usr/bin/env python 213481Sgiacomo.travaglini@arm.com# 313481Sgiacomo.travaglini@arm.com# Copyright 2007 Neal Norwitz 413481Sgiacomo.travaglini@arm.com# Portions Copyright 2007 Google Inc. 513481Sgiacomo.travaglini@arm.com# 613481Sgiacomo.travaglini@arm.com# Licensed under the Apache License, Version 2.0 (the "License"); 713481Sgiacomo.travaglini@arm.com# you may not use this file except in compliance with the License. 813481Sgiacomo.travaglini@arm.com# You may obtain a copy of the License at 913481Sgiacomo.travaglini@arm.com# 1013481Sgiacomo.travaglini@arm.com# http://www.apache.org/licenses/LICENSE-2.0 1113481Sgiacomo.travaglini@arm.com# 1213481Sgiacomo.travaglini@arm.com# Unless required by applicable law or agreed to in writing, software 1313481Sgiacomo.travaglini@arm.com# distributed under the License is distributed on an "AS IS" BASIS, 1413481Sgiacomo.travaglini@arm.com# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1513481Sgiacomo.travaglini@arm.com# See the License for the specific language governing permissions and 1613481Sgiacomo.travaglini@arm.com# limitations under the License. 1713481Sgiacomo.travaglini@arm.com 1813481Sgiacomo.travaglini@arm.com"""Generate an Abstract Syntax Tree (AST) for C++.""" 1913481Sgiacomo.travaglini@arm.com 2013481Sgiacomo.travaglini@arm.com__author__ = 'nnorwitz@google.com (Neal Norwitz)' 2113481Sgiacomo.travaglini@arm.com 2213481Sgiacomo.travaglini@arm.com 2313481Sgiacomo.travaglini@arm.com# TODO: 2413481Sgiacomo.travaglini@arm.com# * Tokens should never be exported, need to convert to Nodes 2513481Sgiacomo.travaglini@arm.com# (return types, parameters, etc.) 2613481Sgiacomo.travaglini@arm.com# * Handle static class data for templatized classes 2713481Sgiacomo.travaglini@arm.com# * Handle casts (both C++ and C-style) 2813481Sgiacomo.travaglini@arm.com# * Handle conditions and loops (if/else, switch, for, while/do) 2913481Sgiacomo.travaglini@arm.com# 3013481Sgiacomo.travaglini@arm.com# TODO much, much later: 3113481Sgiacomo.travaglini@arm.com# * Handle #define 3213481Sgiacomo.travaglini@arm.com# * exceptions 3313481Sgiacomo.travaglini@arm.com 3413481Sgiacomo.travaglini@arm.com 3513481Sgiacomo.travaglini@arm.comtry: 3613481Sgiacomo.travaglini@arm.com # Python 3.x 3713481Sgiacomo.travaglini@arm.com import builtins 3813481Sgiacomo.travaglini@arm.comexcept ImportError: 3913481Sgiacomo.travaglini@arm.com # Python 2.x 4013481Sgiacomo.travaglini@arm.com import __builtin__ as builtins 4113481Sgiacomo.travaglini@arm.com 4213481Sgiacomo.travaglini@arm.comimport sys 4313481Sgiacomo.travaglini@arm.comimport traceback 4413481Sgiacomo.travaglini@arm.com 4513481Sgiacomo.travaglini@arm.comfrom cpp import keywords 4613481Sgiacomo.travaglini@arm.comfrom cpp import tokenize 4713481Sgiacomo.travaglini@arm.comfrom cpp import utils 4813481Sgiacomo.travaglini@arm.com 4913481Sgiacomo.travaglini@arm.com 5013481Sgiacomo.travaglini@arm.comif not hasattr(builtins, 'reversed'): 5113481Sgiacomo.travaglini@arm.com # Support Python 2.3 and earlier. 5213481Sgiacomo.travaglini@arm.com def reversed(seq): 5313481Sgiacomo.travaglini@arm.com for i in range(len(seq)-1, -1, -1): 5413481Sgiacomo.travaglini@arm.com yield seq[i] 5513481Sgiacomo.travaglini@arm.com 5613481Sgiacomo.travaglini@arm.comif not hasattr(builtins, 'next'): 5713481Sgiacomo.travaglini@arm.com # Support Python 2.5 and earlier. 5813481Sgiacomo.travaglini@arm.com def next(obj): 5913481Sgiacomo.travaglini@arm.com return obj.next() 6013481Sgiacomo.travaglini@arm.com 6113481Sgiacomo.travaglini@arm.com 6213481Sgiacomo.travaglini@arm.comVISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3) 6313481Sgiacomo.travaglini@arm.com 6413481Sgiacomo.travaglini@arm.comFUNCTION_NONE = 0x00 6513481Sgiacomo.travaglini@arm.comFUNCTION_CONST = 0x01 6613481Sgiacomo.travaglini@arm.comFUNCTION_VIRTUAL = 0x02 6713481Sgiacomo.travaglini@arm.comFUNCTION_PURE_VIRTUAL = 0x04 6813481Sgiacomo.travaglini@arm.comFUNCTION_CTOR = 0x08 6913481Sgiacomo.travaglini@arm.comFUNCTION_DTOR = 0x10 7013481Sgiacomo.travaglini@arm.comFUNCTION_ATTRIBUTE = 0x20 7113481Sgiacomo.travaglini@arm.comFUNCTION_UNKNOWN_ANNOTATION = 0x40 7213481Sgiacomo.travaglini@arm.comFUNCTION_THROW = 0x80 7313481Sgiacomo.travaglini@arm.comFUNCTION_OVERRIDE = 0x100 7413481Sgiacomo.travaglini@arm.com 7513481Sgiacomo.travaglini@arm.com""" 7613481Sgiacomo.travaglini@arm.comThese are currently unused. Should really handle these properly at some point. 7713481Sgiacomo.travaglini@arm.com 7813481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_INLINE = 0x010000 7913481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_EXTERN = 0x020000 8013481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_STATIC = 0x040000 8113481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_CONST = 0x080000 8213481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_REGISTER = 0x100000 8313481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_VOLATILE = 0x200000 8413481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_MUTABLE = 0x400000 8513481Sgiacomo.travaglini@arm.com 8613481Sgiacomo.travaglini@arm.comTYPE_MODIFIER_MAP = { 8713481Sgiacomo.travaglini@arm.com 'inline': TYPE_MODIFIER_INLINE, 8813481Sgiacomo.travaglini@arm.com 'extern': TYPE_MODIFIER_EXTERN, 8913481Sgiacomo.travaglini@arm.com 'static': TYPE_MODIFIER_STATIC, 9013481Sgiacomo.travaglini@arm.com 'const': TYPE_MODIFIER_CONST, 9113481Sgiacomo.travaglini@arm.com 'register': TYPE_MODIFIER_REGISTER, 9213481Sgiacomo.travaglini@arm.com 'volatile': TYPE_MODIFIER_VOLATILE, 9313481Sgiacomo.travaglini@arm.com 'mutable': TYPE_MODIFIER_MUTABLE, 9413481Sgiacomo.travaglini@arm.com } 9513481Sgiacomo.travaglini@arm.com""" 9613481Sgiacomo.travaglini@arm.com 9713481Sgiacomo.travaglini@arm.com_INTERNAL_TOKEN = 'internal' 9813481Sgiacomo.travaglini@arm.com_NAMESPACE_POP = 'ns-pop' 9913481Sgiacomo.travaglini@arm.com 10013481Sgiacomo.travaglini@arm.com 10113481Sgiacomo.travaglini@arm.com# TODO(nnorwitz): use this as a singleton for templated_types, etc 10213481Sgiacomo.travaglini@arm.com# where we don't want to create a new empty dict each time. It is also const. 10313481Sgiacomo.travaglini@arm.comclass _NullDict(object): 10413481Sgiacomo.travaglini@arm.com __contains__ = lambda self: False 10513481Sgiacomo.travaglini@arm.com keys = values = items = iterkeys = itervalues = iteritems = lambda self: () 10613481Sgiacomo.travaglini@arm.com 10713481Sgiacomo.travaglini@arm.com 10813481Sgiacomo.travaglini@arm.com# TODO(nnorwitz): move AST nodes into a separate module. 10913481Sgiacomo.travaglini@arm.comclass Node(object): 11013481Sgiacomo.travaglini@arm.com """Base AST node.""" 11113481Sgiacomo.travaglini@arm.com 11213481Sgiacomo.travaglini@arm.com def __init__(self, start, end): 11313481Sgiacomo.travaglini@arm.com self.start = start 11413481Sgiacomo.travaglini@arm.com self.end = end 11513481Sgiacomo.travaglini@arm.com 11613481Sgiacomo.travaglini@arm.com def IsDeclaration(self): 11713481Sgiacomo.travaglini@arm.com """Returns bool if this node is a declaration.""" 11813481Sgiacomo.travaglini@arm.com return False 11913481Sgiacomo.travaglini@arm.com 12013481Sgiacomo.travaglini@arm.com def IsDefinition(self): 12113481Sgiacomo.travaglini@arm.com """Returns bool if this node is a definition.""" 12213481Sgiacomo.travaglini@arm.com return False 12313481Sgiacomo.travaglini@arm.com 12413481Sgiacomo.travaglini@arm.com def IsExportable(self): 12513481Sgiacomo.travaglini@arm.com """Returns bool if this node exportable from a header file.""" 12613481Sgiacomo.travaglini@arm.com return False 12713481Sgiacomo.travaglini@arm.com 12813481Sgiacomo.travaglini@arm.com def Requires(self, node): 12913481Sgiacomo.travaglini@arm.com """Does this AST node require the definition of the node passed in?""" 13013481Sgiacomo.travaglini@arm.com return False 13113481Sgiacomo.travaglini@arm.com 13213481Sgiacomo.travaglini@arm.com def XXX__str__(self): 13313481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, '') 13413481Sgiacomo.travaglini@arm.com 13513481Sgiacomo.travaglini@arm.com def _StringHelper(self, name, suffix): 13613481Sgiacomo.travaglini@arm.com if not utils.DEBUG: 13713481Sgiacomo.travaglini@arm.com return '%s(%s)' % (name, suffix) 13813481Sgiacomo.travaglini@arm.com return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix) 13913481Sgiacomo.travaglini@arm.com 14013481Sgiacomo.travaglini@arm.com def __repr__(self): 14113481Sgiacomo.travaglini@arm.com return str(self) 14213481Sgiacomo.travaglini@arm.com 14313481Sgiacomo.travaglini@arm.com 14413481Sgiacomo.travaglini@arm.comclass Define(Node): 14513481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, definition): 14613481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 14713481Sgiacomo.travaglini@arm.com self.name = name 14813481Sgiacomo.travaglini@arm.com self.definition = definition 14913481Sgiacomo.travaglini@arm.com 15013481Sgiacomo.travaglini@arm.com def __str__(self): 15113481Sgiacomo.travaglini@arm.com value = '%s %s' % (self.name, self.definition) 15213481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, value) 15313481Sgiacomo.travaglini@arm.com 15413481Sgiacomo.travaglini@arm.com 15513481Sgiacomo.travaglini@arm.comclass Include(Node): 15613481Sgiacomo.travaglini@arm.com def __init__(self, start, end, filename, system): 15713481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 15813481Sgiacomo.travaglini@arm.com self.filename = filename 15913481Sgiacomo.travaglini@arm.com self.system = system 16013481Sgiacomo.travaglini@arm.com 16113481Sgiacomo.travaglini@arm.com def __str__(self): 16213481Sgiacomo.travaglini@arm.com fmt = '"%s"' 16313481Sgiacomo.travaglini@arm.com if self.system: 16413481Sgiacomo.travaglini@arm.com fmt = '<%s>' 16513481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, fmt % self.filename) 16613481Sgiacomo.travaglini@arm.com 16713481Sgiacomo.travaglini@arm.com 16813481Sgiacomo.travaglini@arm.comclass Goto(Node): 16913481Sgiacomo.travaglini@arm.com def __init__(self, start, end, label): 17013481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 17113481Sgiacomo.travaglini@arm.com self.label = label 17213481Sgiacomo.travaglini@arm.com 17313481Sgiacomo.travaglini@arm.com def __str__(self): 17413481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, str(self.label)) 17513481Sgiacomo.travaglini@arm.com 17613481Sgiacomo.travaglini@arm.com 17713481Sgiacomo.travaglini@arm.comclass Expr(Node): 17813481Sgiacomo.travaglini@arm.com def __init__(self, start, end, expr): 17913481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 18013481Sgiacomo.travaglini@arm.com self.expr = expr 18113481Sgiacomo.travaglini@arm.com 18213481Sgiacomo.travaglini@arm.com def Requires(self, node): 18313481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): impl. 18413481Sgiacomo.travaglini@arm.com return False 18513481Sgiacomo.travaglini@arm.com 18613481Sgiacomo.travaglini@arm.com def __str__(self): 18713481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, str(self.expr)) 18813481Sgiacomo.travaglini@arm.com 18913481Sgiacomo.travaglini@arm.com 19013481Sgiacomo.travaglini@arm.comclass Return(Expr): 19113481Sgiacomo.travaglini@arm.com pass 19213481Sgiacomo.travaglini@arm.com 19313481Sgiacomo.travaglini@arm.com 19413481Sgiacomo.travaglini@arm.comclass Delete(Expr): 19513481Sgiacomo.travaglini@arm.com pass 19613481Sgiacomo.travaglini@arm.com 19713481Sgiacomo.travaglini@arm.com 19813481Sgiacomo.travaglini@arm.comclass Friend(Expr): 19913481Sgiacomo.travaglini@arm.com def __init__(self, start, end, expr, namespace): 20013481Sgiacomo.travaglini@arm.com Expr.__init__(self, start, end, expr) 20113481Sgiacomo.travaglini@arm.com self.namespace = namespace[:] 20213481Sgiacomo.travaglini@arm.com 20313481Sgiacomo.travaglini@arm.com 20413481Sgiacomo.travaglini@arm.comclass Using(Node): 20513481Sgiacomo.travaglini@arm.com def __init__(self, start, end, names): 20613481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 20713481Sgiacomo.travaglini@arm.com self.names = names 20813481Sgiacomo.travaglini@arm.com 20913481Sgiacomo.travaglini@arm.com def __str__(self): 21013481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, str(self.names)) 21113481Sgiacomo.travaglini@arm.com 21213481Sgiacomo.travaglini@arm.com 21313481Sgiacomo.travaglini@arm.comclass Parameter(Node): 21413481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, parameter_type, default): 21513481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 21613481Sgiacomo.travaglini@arm.com self.name = name 21713481Sgiacomo.travaglini@arm.com self.type = parameter_type 21813481Sgiacomo.travaglini@arm.com self.default = default 21913481Sgiacomo.travaglini@arm.com 22013481Sgiacomo.travaglini@arm.com def Requires(self, node): 22113481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle namespaces, etc. 22213481Sgiacomo.travaglini@arm.com return self.type.name == node.name 22313481Sgiacomo.travaglini@arm.com 22413481Sgiacomo.travaglini@arm.com def __str__(self): 22513481Sgiacomo.travaglini@arm.com name = str(self.type) 22613481Sgiacomo.travaglini@arm.com suffix = '%s %s' % (name, self.name) 22713481Sgiacomo.travaglini@arm.com if self.default: 22813481Sgiacomo.travaglini@arm.com suffix += ' = ' + ''.join([d.name for d in self.default]) 22913481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, suffix) 23013481Sgiacomo.travaglini@arm.com 23113481Sgiacomo.travaglini@arm.com 23213481Sgiacomo.travaglini@arm.comclass _GenericDeclaration(Node): 23313481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, namespace): 23413481Sgiacomo.travaglini@arm.com Node.__init__(self, start, end) 23513481Sgiacomo.travaglini@arm.com self.name = name 23613481Sgiacomo.travaglini@arm.com self.namespace = namespace[:] 23713481Sgiacomo.travaglini@arm.com 23813481Sgiacomo.travaglini@arm.com def FullName(self): 23913481Sgiacomo.travaglini@arm.com prefix = '' 24013481Sgiacomo.travaglini@arm.com if self.namespace and self.namespace[-1]: 24113481Sgiacomo.travaglini@arm.com prefix = '::'.join(self.namespace) + '::' 24213481Sgiacomo.travaglini@arm.com return prefix + self.name 24313481Sgiacomo.travaglini@arm.com 24413481Sgiacomo.travaglini@arm.com def _TypeStringHelper(self, suffix): 24513481Sgiacomo.travaglini@arm.com if self.namespace: 24613481Sgiacomo.travaglini@arm.com names = [n or '<anonymous>' for n in self.namespace] 24713481Sgiacomo.travaglini@arm.com suffix += ' in ' + '::'.join(names) 24813481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, suffix) 24913481Sgiacomo.travaglini@arm.com 25013481Sgiacomo.travaglini@arm.com 25113481Sgiacomo.travaglini@arm.com# TODO(nnorwitz): merge with Parameter in some way? 25213481Sgiacomo.travaglini@arm.comclass VariableDeclaration(_GenericDeclaration): 25313481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, var_type, initial_value, namespace): 25413481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, namespace) 25513481Sgiacomo.travaglini@arm.com self.type = var_type 25613481Sgiacomo.travaglini@arm.com self.initial_value = initial_value 25713481Sgiacomo.travaglini@arm.com 25813481Sgiacomo.travaglini@arm.com def Requires(self, node): 25913481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle namespaces, etc. 26013481Sgiacomo.travaglini@arm.com return self.type.name == node.name 26113481Sgiacomo.travaglini@arm.com 26213481Sgiacomo.travaglini@arm.com def ToString(self): 26313481Sgiacomo.travaglini@arm.com """Return a string that tries to reconstitute the variable decl.""" 26413481Sgiacomo.travaglini@arm.com suffix = '%s %s' % (self.type, self.name) 26513481Sgiacomo.travaglini@arm.com if self.initial_value: 26613481Sgiacomo.travaglini@arm.com suffix += ' = ' + self.initial_value 26713481Sgiacomo.travaglini@arm.com return suffix 26813481Sgiacomo.travaglini@arm.com 26913481Sgiacomo.travaglini@arm.com def __str__(self): 27013481Sgiacomo.travaglini@arm.com return self._StringHelper(self.__class__.__name__, self.ToString()) 27113481Sgiacomo.travaglini@arm.com 27213481Sgiacomo.travaglini@arm.com 27313481Sgiacomo.travaglini@arm.comclass Typedef(_GenericDeclaration): 27413481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, alias, namespace): 27513481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, namespace) 27613481Sgiacomo.travaglini@arm.com self.alias = alias 27713481Sgiacomo.travaglini@arm.com 27813481Sgiacomo.travaglini@arm.com def IsDefinition(self): 27913481Sgiacomo.travaglini@arm.com return True 28013481Sgiacomo.travaglini@arm.com 28113481Sgiacomo.travaglini@arm.com def IsExportable(self): 28213481Sgiacomo.travaglini@arm.com return True 28313481Sgiacomo.travaglini@arm.com 28413481Sgiacomo.travaglini@arm.com def Requires(self, node): 28513481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle namespaces, etc. 28613481Sgiacomo.travaglini@arm.com name = node.name 28713481Sgiacomo.travaglini@arm.com for token in self.alias: 28813481Sgiacomo.travaglini@arm.com if token is not None and name == token.name: 28913481Sgiacomo.travaglini@arm.com return True 29013481Sgiacomo.travaglini@arm.com return False 29113481Sgiacomo.travaglini@arm.com 29213481Sgiacomo.travaglini@arm.com def __str__(self): 29313481Sgiacomo.travaglini@arm.com suffix = '%s, %s' % (self.name, self.alias) 29413481Sgiacomo.travaglini@arm.com return self._TypeStringHelper(suffix) 29513481Sgiacomo.travaglini@arm.com 29613481Sgiacomo.travaglini@arm.com 29713481Sgiacomo.travaglini@arm.comclass _NestedType(_GenericDeclaration): 29813481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, fields, namespace): 29913481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, namespace) 30013481Sgiacomo.travaglini@arm.com self.fields = fields 30113481Sgiacomo.travaglini@arm.com 30213481Sgiacomo.travaglini@arm.com def IsDefinition(self): 30313481Sgiacomo.travaglini@arm.com return True 30413481Sgiacomo.travaglini@arm.com 30513481Sgiacomo.travaglini@arm.com def IsExportable(self): 30613481Sgiacomo.travaglini@arm.com return True 30713481Sgiacomo.travaglini@arm.com 30813481Sgiacomo.travaglini@arm.com def __str__(self): 30913481Sgiacomo.travaglini@arm.com suffix = '%s, {%s}' % (self.name, self.fields) 31013481Sgiacomo.travaglini@arm.com return self._TypeStringHelper(suffix) 31113481Sgiacomo.travaglini@arm.com 31213481Sgiacomo.travaglini@arm.com 31313481Sgiacomo.travaglini@arm.comclass Union(_NestedType): 31413481Sgiacomo.travaglini@arm.com pass 31513481Sgiacomo.travaglini@arm.com 31613481Sgiacomo.travaglini@arm.com 31713481Sgiacomo.travaglini@arm.comclass Enum(_NestedType): 31813481Sgiacomo.travaglini@arm.com pass 31913481Sgiacomo.travaglini@arm.com 32013481Sgiacomo.travaglini@arm.com 32113481Sgiacomo.travaglini@arm.comclass Class(_GenericDeclaration): 32213481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, bases, templated_types, body, namespace): 32313481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, namespace) 32413481Sgiacomo.travaglini@arm.com self.bases = bases 32513481Sgiacomo.travaglini@arm.com self.body = body 32613481Sgiacomo.travaglini@arm.com self.templated_types = templated_types 32713481Sgiacomo.travaglini@arm.com 32813481Sgiacomo.travaglini@arm.com def IsDeclaration(self): 32913481Sgiacomo.travaglini@arm.com return self.bases is None and self.body is None 33013481Sgiacomo.travaglini@arm.com 33113481Sgiacomo.travaglini@arm.com def IsDefinition(self): 33213481Sgiacomo.travaglini@arm.com return not self.IsDeclaration() 33313481Sgiacomo.travaglini@arm.com 33413481Sgiacomo.travaglini@arm.com def IsExportable(self): 33513481Sgiacomo.travaglini@arm.com return not self.IsDeclaration() 33613481Sgiacomo.travaglini@arm.com 33713481Sgiacomo.travaglini@arm.com def Requires(self, node): 33813481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle namespaces, etc. 33913481Sgiacomo.travaglini@arm.com if self.bases: 34013481Sgiacomo.travaglini@arm.com for token_list in self.bases: 34113481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): bases are tokens, do name comparision. 34213481Sgiacomo.travaglini@arm.com for token in token_list: 34313481Sgiacomo.travaglini@arm.com if token.name == node.name: 34413481Sgiacomo.travaglini@arm.com return True 34513481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): search in body too. 34613481Sgiacomo.travaglini@arm.com return False 34713481Sgiacomo.travaglini@arm.com 34813481Sgiacomo.travaglini@arm.com def __str__(self): 34913481Sgiacomo.travaglini@arm.com name = self.name 35013481Sgiacomo.travaglini@arm.com if self.templated_types: 35113481Sgiacomo.travaglini@arm.com name += '<%s>' % self.templated_types 35213481Sgiacomo.travaglini@arm.com suffix = '%s, %s, %s' % (name, self.bases, self.body) 35313481Sgiacomo.travaglini@arm.com return self._TypeStringHelper(suffix) 35413481Sgiacomo.travaglini@arm.com 35513481Sgiacomo.travaglini@arm.com 35613481Sgiacomo.travaglini@arm.comclass Struct(Class): 35713481Sgiacomo.travaglini@arm.com pass 35813481Sgiacomo.travaglini@arm.com 35913481Sgiacomo.travaglini@arm.com 36013481Sgiacomo.travaglini@arm.comclass Function(_GenericDeclaration): 36113481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, return_type, parameters, 36213481Sgiacomo.travaglini@arm.com modifiers, templated_types, body, namespace): 36313481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, namespace) 36413481Sgiacomo.travaglini@arm.com converter = TypeConverter(namespace) 36513481Sgiacomo.travaglini@arm.com self.return_type = converter.CreateReturnType(return_type) 36613481Sgiacomo.travaglini@arm.com self.parameters = converter.ToParameters(parameters) 36713481Sgiacomo.travaglini@arm.com self.modifiers = modifiers 36813481Sgiacomo.travaglini@arm.com self.body = body 36913481Sgiacomo.travaglini@arm.com self.templated_types = templated_types 37013481Sgiacomo.travaglini@arm.com 37113481Sgiacomo.travaglini@arm.com def IsDeclaration(self): 37213481Sgiacomo.travaglini@arm.com return self.body is None 37313481Sgiacomo.travaglini@arm.com 37413481Sgiacomo.travaglini@arm.com def IsDefinition(self): 37513481Sgiacomo.travaglini@arm.com return self.body is not None 37613481Sgiacomo.travaglini@arm.com 37713481Sgiacomo.travaglini@arm.com def IsExportable(self): 37813481Sgiacomo.travaglini@arm.com if self.return_type and 'static' in self.return_type.modifiers: 37913481Sgiacomo.travaglini@arm.com return False 38013481Sgiacomo.travaglini@arm.com return None not in self.namespace 38113481Sgiacomo.travaglini@arm.com 38213481Sgiacomo.travaglini@arm.com def Requires(self, node): 38313481Sgiacomo.travaglini@arm.com if self.parameters: 38413481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): parameters are tokens, do name comparision. 38513481Sgiacomo.travaglini@arm.com for p in self.parameters: 38613481Sgiacomo.travaglini@arm.com if p.name == node.name: 38713481Sgiacomo.travaglini@arm.com return True 38813481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): search in body too. 38913481Sgiacomo.travaglini@arm.com return False 39013481Sgiacomo.travaglini@arm.com 39113481Sgiacomo.travaglini@arm.com def __str__(self): 39213481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): add templated_types. 39313481Sgiacomo.travaglini@arm.com suffix = ('%s %s(%s), 0x%02x, %s' % 39413481Sgiacomo.travaglini@arm.com (self.return_type, self.name, self.parameters, 39513481Sgiacomo.travaglini@arm.com self.modifiers, self.body)) 39613481Sgiacomo.travaglini@arm.com return self._TypeStringHelper(suffix) 39713481Sgiacomo.travaglini@arm.com 39813481Sgiacomo.travaglini@arm.com 39913481Sgiacomo.travaglini@arm.comclass Method(Function): 40013481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, in_class, return_type, parameters, 40113481Sgiacomo.travaglini@arm.com modifiers, templated_types, body, namespace): 40213481Sgiacomo.travaglini@arm.com Function.__init__(self, start, end, name, return_type, parameters, 40313481Sgiacomo.travaglini@arm.com modifiers, templated_types, body, namespace) 40413481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): in_class could also be a namespace which can 40513481Sgiacomo.travaglini@arm.com # mess up finding functions properly. 40613481Sgiacomo.travaglini@arm.com self.in_class = in_class 40713481Sgiacomo.travaglini@arm.com 40813481Sgiacomo.travaglini@arm.com 40913481Sgiacomo.travaglini@arm.comclass Type(_GenericDeclaration): 41013481Sgiacomo.travaglini@arm.com """Type used for any variable (eg class, primitive, struct, etc).""" 41113481Sgiacomo.travaglini@arm.com 41213481Sgiacomo.travaglini@arm.com def __init__(self, start, end, name, templated_types, modifiers, 41313481Sgiacomo.travaglini@arm.com reference, pointer, array): 41413481Sgiacomo.travaglini@arm.com """ 41513481Sgiacomo.travaglini@arm.com Args: 41613481Sgiacomo.travaglini@arm.com name: str name of main type 41713481Sgiacomo.travaglini@arm.com templated_types: [Class (Type?)] template type info between <> 41813481Sgiacomo.travaglini@arm.com modifiers: [str] type modifiers (keywords) eg, const, mutable, etc. 41913481Sgiacomo.travaglini@arm.com reference, pointer, array: bools 42013481Sgiacomo.travaglini@arm.com """ 42113481Sgiacomo.travaglini@arm.com _GenericDeclaration.__init__(self, start, end, name, []) 42213481Sgiacomo.travaglini@arm.com self.templated_types = templated_types 42313481Sgiacomo.travaglini@arm.com if not name and modifiers: 42413481Sgiacomo.travaglini@arm.com self.name = modifiers.pop() 42513481Sgiacomo.travaglini@arm.com self.modifiers = modifiers 42613481Sgiacomo.travaglini@arm.com self.reference = reference 42713481Sgiacomo.travaglini@arm.com self.pointer = pointer 42813481Sgiacomo.travaglini@arm.com self.array = array 42913481Sgiacomo.travaglini@arm.com 43013481Sgiacomo.travaglini@arm.com def __str__(self): 43113481Sgiacomo.travaglini@arm.com prefix = '' 43213481Sgiacomo.travaglini@arm.com if self.modifiers: 43313481Sgiacomo.travaglini@arm.com prefix = ' '.join(self.modifiers) + ' ' 43413481Sgiacomo.travaglini@arm.com name = str(self.name) 43513481Sgiacomo.travaglini@arm.com if self.templated_types: 43613481Sgiacomo.travaglini@arm.com name += '<%s>' % self.templated_types 43713481Sgiacomo.travaglini@arm.com suffix = prefix + name 43813481Sgiacomo.travaglini@arm.com if self.reference: 43913481Sgiacomo.travaglini@arm.com suffix += '&' 44013481Sgiacomo.travaglini@arm.com if self.pointer: 44113481Sgiacomo.travaglini@arm.com suffix += '*' 44213481Sgiacomo.travaglini@arm.com if self.array: 44313481Sgiacomo.travaglini@arm.com suffix += '[]' 44413481Sgiacomo.travaglini@arm.com return self._TypeStringHelper(suffix) 44513481Sgiacomo.travaglini@arm.com 44613481Sgiacomo.travaglini@arm.com # By definition, Is* are always False. A Type can only exist in 44713481Sgiacomo.travaglini@arm.com # some sort of variable declaration, parameter, or return value. 44813481Sgiacomo.travaglini@arm.com def IsDeclaration(self): 44913481Sgiacomo.travaglini@arm.com return False 45013481Sgiacomo.travaglini@arm.com 45113481Sgiacomo.travaglini@arm.com def IsDefinition(self): 45213481Sgiacomo.travaglini@arm.com return False 45313481Sgiacomo.travaglini@arm.com 45413481Sgiacomo.travaglini@arm.com def IsExportable(self): 45513481Sgiacomo.travaglini@arm.com return False 45613481Sgiacomo.travaglini@arm.com 45713481Sgiacomo.travaglini@arm.com 45813481Sgiacomo.travaglini@arm.comclass TypeConverter(object): 45913481Sgiacomo.travaglini@arm.com 46013481Sgiacomo.travaglini@arm.com def __init__(self, namespace_stack): 46113481Sgiacomo.travaglini@arm.com self.namespace_stack = namespace_stack 46213481Sgiacomo.travaglini@arm.com 46313481Sgiacomo.travaglini@arm.com def _GetTemplateEnd(self, tokens, start): 46413481Sgiacomo.travaglini@arm.com count = 1 46513481Sgiacomo.travaglini@arm.com end = start 46613481Sgiacomo.travaglini@arm.com while 1: 46713481Sgiacomo.travaglini@arm.com token = tokens[end] 46813481Sgiacomo.travaglini@arm.com end += 1 46913481Sgiacomo.travaglini@arm.com if token.name == '<': 47013481Sgiacomo.travaglini@arm.com count += 1 47113481Sgiacomo.travaglini@arm.com elif token.name == '>': 47213481Sgiacomo.travaglini@arm.com count -= 1 47313481Sgiacomo.travaglini@arm.com if count == 0: 47413481Sgiacomo.travaglini@arm.com break 47513481Sgiacomo.travaglini@arm.com return tokens[start:end-1], end 47613481Sgiacomo.travaglini@arm.com 47713481Sgiacomo.travaglini@arm.com def ToType(self, tokens): 47813481Sgiacomo.travaglini@arm.com """Convert [Token,...] to [Class(...), ] useful for base classes. 47913481Sgiacomo.travaglini@arm.com For example, code like class Foo : public Bar<x, y> { ... }; 48013481Sgiacomo.travaglini@arm.com the "Bar<x, y>" portion gets converted to an AST. 48113481Sgiacomo.travaglini@arm.com 48213481Sgiacomo.travaglini@arm.com Returns: 48313481Sgiacomo.travaglini@arm.com [Class(...), ...] 48413481Sgiacomo.travaglini@arm.com """ 48513481Sgiacomo.travaglini@arm.com result = [] 48613481Sgiacomo.travaglini@arm.com name_tokens = [] 48713481Sgiacomo.travaglini@arm.com reference = pointer = array = False 48813481Sgiacomo.travaglini@arm.com 48913481Sgiacomo.travaglini@arm.com def AddType(templated_types): 49013481Sgiacomo.travaglini@arm.com # Partition tokens into name and modifier tokens. 49113481Sgiacomo.travaglini@arm.com names = [] 49213481Sgiacomo.travaglini@arm.com modifiers = [] 49313481Sgiacomo.travaglini@arm.com for t in name_tokens: 49413481Sgiacomo.travaglini@arm.com if keywords.IsKeyword(t.name): 49513481Sgiacomo.travaglini@arm.com modifiers.append(t.name) 49613481Sgiacomo.travaglini@arm.com else: 49713481Sgiacomo.travaglini@arm.com names.append(t.name) 49813481Sgiacomo.travaglini@arm.com name = ''.join(names) 49913481Sgiacomo.travaglini@arm.com if name_tokens: 50013481Sgiacomo.travaglini@arm.com result.append(Type(name_tokens[0].start, name_tokens[-1].end, 50113481Sgiacomo.travaglini@arm.com name, templated_types, modifiers, 50213481Sgiacomo.travaglini@arm.com reference, pointer, array)) 50313481Sgiacomo.travaglini@arm.com del name_tokens[:] 50413481Sgiacomo.travaglini@arm.com 50513481Sgiacomo.travaglini@arm.com i = 0 50613481Sgiacomo.travaglini@arm.com end = len(tokens) 50713481Sgiacomo.travaglini@arm.com while i < end: 50813481Sgiacomo.travaglini@arm.com token = tokens[i] 50913481Sgiacomo.travaglini@arm.com if token.name == '<': 51013481Sgiacomo.travaglini@arm.com new_tokens, new_end = self._GetTemplateEnd(tokens, i+1) 51113481Sgiacomo.travaglini@arm.com AddType(self.ToType(new_tokens)) 51213481Sgiacomo.travaglini@arm.com # If there is a comma after the template, we need to consume 51313481Sgiacomo.travaglini@arm.com # that here otherwise it becomes part of the name. 51413481Sgiacomo.travaglini@arm.com i = new_end 51513481Sgiacomo.travaglini@arm.com reference = pointer = array = False 51613481Sgiacomo.travaglini@arm.com elif token.name == ',': 51713481Sgiacomo.travaglini@arm.com AddType([]) 51813481Sgiacomo.travaglini@arm.com reference = pointer = array = False 51913481Sgiacomo.travaglini@arm.com elif token.name == '*': 52013481Sgiacomo.travaglini@arm.com pointer = True 52113481Sgiacomo.travaglini@arm.com elif token.name == '&': 52213481Sgiacomo.travaglini@arm.com reference = True 52313481Sgiacomo.travaglini@arm.com elif token.name == '[': 52413481Sgiacomo.travaglini@arm.com pointer = True 52513481Sgiacomo.travaglini@arm.com elif token.name == ']': 52613481Sgiacomo.travaglini@arm.com pass 52713481Sgiacomo.travaglini@arm.com else: 52813481Sgiacomo.travaglini@arm.com name_tokens.append(token) 52913481Sgiacomo.travaglini@arm.com i += 1 53013481Sgiacomo.travaglini@arm.com 53113481Sgiacomo.travaglini@arm.com if name_tokens: 53213481Sgiacomo.travaglini@arm.com # No '<' in the tokens, just a simple name and no template. 53313481Sgiacomo.travaglini@arm.com AddType([]) 53413481Sgiacomo.travaglini@arm.com return result 53513481Sgiacomo.travaglini@arm.com 53613481Sgiacomo.travaglini@arm.com def DeclarationToParts(self, parts, needs_name_removed): 53713481Sgiacomo.travaglini@arm.com name = None 53813481Sgiacomo.travaglini@arm.com default = [] 53913481Sgiacomo.travaglini@arm.com if needs_name_removed: 54013481Sgiacomo.travaglini@arm.com # Handle default (initial) values properly. 54113481Sgiacomo.travaglini@arm.com for i, t in enumerate(parts): 54213481Sgiacomo.travaglini@arm.com if t.name == '=': 54313481Sgiacomo.travaglini@arm.com default = parts[i+1:] 54413481Sgiacomo.travaglini@arm.com name = parts[i-1].name 54513481Sgiacomo.travaglini@arm.com if name == ']' and parts[i-2].name == '[': 54613481Sgiacomo.travaglini@arm.com name = parts[i-3].name 54713481Sgiacomo.travaglini@arm.com i -= 1 54813481Sgiacomo.travaglini@arm.com parts = parts[:i-1] 54913481Sgiacomo.travaglini@arm.com break 55013481Sgiacomo.travaglini@arm.com else: 55113481Sgiacomo.travaglini@arm.com if parts[-1].token_type == tokenize.NAME: 55213481Sgiacomo.travaglini@arm.com name = parts.pop().name 55313481Sgiacomo.travaglini@arm.com else: 55413481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): this is a hack that happens for code like 55513481Sgiacomo.travaglini@arm.com # Register(Foo<T>); where it thinks this is a function call 55613481Sgiacomo.travaglini@arm.com # but it's actually a declaration. 55713481Sgiacomo.travaglini@arm.com name = '???' 55813481Sgiacomo.travaglini@arm.com modifiers = [] 55913481Sgiacomo.travaglini@arm.com type_name = [] 56013481Sgiacomo.travaglini@arm.com other_tokens = [] 56113481Sgiacomo.travaglini@arm.com templated_types = [] 56213481Sgiacomo.travaglini@arm.com i = 0 56313481Sgiacomo.travaglini@arm.com end = len(parts) 56413481Sgiacomo.travaglini@arm.com while i < end: 56513481Sgiacomo.travaglini@arm.com p = parts[i] 56613481Sgiacomo.travaglini@arm.com if keywords.IsKeyword(p.name): 56713481Sgiacomo.travaglini@arm.com modifiers.append(p.name) 56813481Sgiacomo.travaglini@arm.com elif p.name == '<': 56913481Sgiacomo.travaglini@arm.com templated_tokens, new_end = self._GetTemplateEnd(parts, i+1) 57013481Sgiacomo.travaglini@arm.com templated_types = self.ToType(templated_tokens) 57113481Sgiacomo.travaglini@arm.com i = new_end - 1 57213481Sgiacomo.travaglini@arm.com # Don't add a spurious :: to data members being initialized. 57313481Sgiacomo.travaglini@arm.com next_index = i + 1 57413481Sgiacomo.travaglini@arm.com if next_index < end and parts[next_index].name == '::': 57513481Sgiacomo.travaglini@arm.com i += 1 57613481Sgiacomo.travaglini@arm.com elif p.name in ('[', ']', '='): 57713481Sgiacomo.travaglini@arm.com # These are handled elsewhere. 57813481Sgiacomo.travaglini@arm.com other_tokens.append(p) 57913481Sgiacomo.travaglini@arm.com elif p.name not in ('*', '&', '>'): 58013481Sgiacomo.travaglini@arm.com # Ensure that names have a space between them. 58113481Sgiacomo.travaglini@arm.com if (type_name and type_name[-1].token_type == tokenize.NAME and 58213481Sgiacomo.travaglini@arm.com p.token_type == tokenize.NAME): 58313481Sgiacomo.travaglini@arm.com type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0)) 58413481Sgiacomo.travaglini@arm.com type_name.append(p) 58513481Sgiacomo.travaglini@arm.com else: 58613481Sgiacomo.travaglini@arm.com other_tokens.append(p) 58713481Sgiacomo.travaglini@arm.com i += 1 58813481Sgiacomo.travaglini@arm.com type_name = ''.join([t.name for t in type_name]) 58913481Sgiacomo.travaglini@arm.com return name, type_name, templated_types, modifiers, default, other_tokens 59013481Sgiacomo.travaglini@arm.com 59113481Sgiacomo.travaglini@arm.com def ToParameters(self, tokens): 59213481Sgiacomo.travaglini@arm.com if not tokens: 59313481Sgiacomo.travaglini@arm.com return [] 59413481Sgiacomo.travaglini@arm.com 59513481Sgiacomo.travaglini@arm.com result = [] 59613481Sgiacomo.travaglini@arm.com name = type_name = '' 59713481Sgiacomo.travaglini@arm.com type_modifiers = [] 59813481Sgiacomo.travaglini@arm.com pointer = reference = array = False 59913481Sgiacomo.travaglini@arm.com first_token = None 60013481Sgiacomo.travaglini@arm.com default = [] 60113481Sgiacomo.travaglini@arm.com 60213481Sgiacomo.travaglini@arm.com def AddParameter(end): 60313481Sgiacomo.travaglini@arm.com if default: 60413481Sgiacomo.travaglini@arm.com del default[0] # Remove flag. 60513481Sgiacomo.travaglini@arm.com parts = self.DeclarationToParts(type_modifiers, True) 60613481Sgiacomo.travaglini@arm.com (name, type_name, templated_types, modifiers, 60713481Sgiacomo.travaglini@arm.com unused_default, unused_other_tokens) = parts 60813481Sgiacomo.travaglini@arm.com parameter_type = Type(first_token.start, first_token.end, 60913481Sgiacomo.travaglini@arm.com type_name, templated_types, modifiers, 61013481Sgiacomo.travaglini@arm.com reference, pointer, array) 61113481Sgiacomo.travaglini@arm.com p = Parameter(first_token.start, end, name, 61213481Sgiacomo.travaglini@arm.com parameter_type, default) 61313481Sgiacomo.travaglini@arm.com result.append(p) 61413481Sgiacomo.travaglini@arm.com 61513481Sgiacomo.travaglini@arm.com template_count = 0 61613481Sgiacomo.travaglini@arm.com for s in tokens: 61713481Sgiacomo.travaglini@arm.com if not first_token: 61813481Sgiacomo.travaglini@arm.com first_token = s 61913481Sgiacomo.travaglini@arm.com if s.name == '<': 62013481Sgiacomo.travaglini@arm.com template_count += 1 62113481Sgiacomo.travaglini@arm.com elif s.name == '>': 62213481Sgiacomo.travaglini@arm.com template_count -= 1 62313481Sgiacomo.travaglini@arm.com if template_count > 0: 62413481Sgiacomo.travaglini@arm.com type_modifiers.append(s) 62513481Sgiacomo.travaglini@arm.com continue 62613481Sgiacomo.travaglini@arm.com 62713481Sgiacomo.travaglini@arm.com if s.name == ',': 62813481Sgiacomo.travaglini@arm.com AddParameter(s.start) 62913481Sgiacomo.travaglini@arm.com name = type_name = '' 63013481Sgiacomo.travaglini@arm.com type_modifiers = [] 63113481Sgiacomo.travaglini@arm.com pointer = reference = array = False 63213481Sgiacomo.travaglini@arm.com first_token = None 63313481Sgiacomo.travaglini@arm.com default = [] 63413481Sgiacomo.travaglini@arm.com elif s.name == '*': 63513481Sgiacomo.travaglini@arm.com pointer = True 63613481Sgiacomo.travaglini@arm.com elif s.name == '&': 63713481Sgiacomo.travaglini@arm.com reference = True 63813481Sgiacomo.travaglini@arm.com elif s.name == '[': 63913481Sgiacomo.travaglini@arm.com array = True 64013481Sgiacomo.travaglini@arm.com elif s.name == ']': 64113481Sgiacomo.travaglini@arm.com pass # Just don't add to type_modifiers. 64213481Sgiacomo.travaglini@arm.com elif s.name == '=': 64313481Sgiacomo.travaglini@arm.com # Got a default value. Add any value (None) as a flag. 64413481Sgiacomo.travaglini@arm.com default.append(None) 64513481Sgiacomo.travaglini@arm.com elif default: 64613481Sgiacomo.travaglini@arm.com default.append(s) 64713481Sgiacomo.travaglini@arm.com else: 64813481Sgiacomo.travaglini@arm.com type_modifiers.append(s) 64913481Sgiacomo.travaglini@arm.com AddParameter(tokens[-1].end) 65013481Sgiacomo.travaglini@arm.com return result 65113481Sgiacomo.travaglini@arm.com 65213481Sgiacomo.travaglini@arm.com def CreateReturnType(self, return_type_seq): 65313481Sgiacomo.travaglini@arm.com if not return_type_seq: 65413481Sgiacomo.travaglini@arm.com return None 65513481Sgiacomo.travaglini@arm.com start = return_type_seq[0].start 65613481Sgiacomo.travaglini@arm.com end = return_type_seq[-1].end 65713481Sgiacomo.travaglini@arm.com _, name, templated_types, modifiers, default, other_tokens = \ 65813481Sgiacomo.travaglini@arm.com self.DeclarationToParts(return_type_seq, False) 65913481Sgiacomo.travaglini@arm.com names = [n.name for n in other_tokens] 66013481Sgiacomo.travaglini@arm.com reference = '&' in names 66113481Sgiacomo.travaglini@arm.com pointer = '*' in names 66213481Sgiacomo.travaglini@arm.com array = '[' in names 66313481Sgiacomo.travaglini@arm.com return Type(start, end, name, templated_types, modifiers, 66413481Sgiacomo.travaglini@arm.com reference, pointer, array) 66513481Sgiacomo.travaglini@arm.com 66613481Sgiacomo.travaglini@arm.com def GetTemplateIndices(self, names): 66713481Sgiacomo.travaglini@arm.com # names is a list of strings. 66813481Sgiacomo.travaglini@arm.com start = names.index('<') 66913481Sgiacomo.travaglini@arm.com end = len(names) - 1 67013481Sgiacomo.travaglini@arm.com while end > 0: 67113481Sgiacomo.travaglini@arm.com if names[end] == '>': 67213481Sgiacomo.travaglini@arm.com break 67313481Sgiacomo.travaglini@arm.com end -= 1 67413481Sgiacomo.travaglini@arm.com return start, end+1 67513481Sgiacomo.travaglini@arm.com 67613481Sgiacomo.travaglini@arm.comclass AstBuilder(object): 67713481Sgiacomo.travaglini@arm.com def __init__(self, token_stream, filename, in_class='', visibility=None, 67813481Sgiacomo.travaglini@arm.com namespace_stack=[]): 67913481Sgiacomo.travaglini@arm.com self.tokens = token_stream 68013481Sgiacomo.travaglini@arm.com self.filename = filename 68113481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): use a better data structure (deque) for the queue. 68213481Sgiacomo.travaglini@arm.com # Switching directions of the "queue" improved perf by about 25%. 68313481Sgiacomo.travaglini@arm.com # Using a deque should be even better since we access from both sides. 68413481Sgiacomo.travaglini@arm.com self.token_queue = [] 68513481Sgiacomo.travaglini@arm.com self.namespace_stack = namespace_stack[:] 68613481Sgiacomo.travaglini@arm.com self.in_class = in_class 68713481Sgiacomo.travaglini@arm.com if in_class is None: 68813481Sgiacomo.travaglini@arm.com self.in_class_name_only = None 68913481Sgiacomo.travaglini@arm.com else: 69013481Sgiacomo.travaglini@arm.com self.in_class_name_only = in_class.split('::')[-1] 69113481Sgiacomo.travaglini@arm.com self.visibility = visibility 69213481Sgiacomo.travaglini@arm.com self.in_function = False 69313481Sgiacomo.travaglini@arm.com self.current_token = None 69413481Sgiacomo.travaglini@arm.com # Keep the state whether we are currently handling a typedef or not. 69513481Sgiacomo.travaglini@arm.com self._handling_typedef = False 69613481Sgiacomo.travaglini@arm.com 69713481Sgiacomo.travaglini@arm.com self.converter = TypeConverter(self.namespace_stack) 69813481Sgiacomo.travaglini@arm.com 69913481Sgiacomo.travaglini@arm.com def HandleError(self, msg, token): 70013481Sgiacomo.travaglini@arm.com printable_queue = list(reversed(self.token_queue[-20:])) 70113481Sgiacomo.travaglini@arm.com sys.stderr.write('Got %s in %s @ %s %s\n' % 70213481Sgiacomo.travaglini@arm.com (msg, self.filename, token, printable_queue)) 70313481Sgiacomo.travaglini@arm.com 70413481Sgiacomo.travaglini@arm.com def Generate(self): 70513481Sgiacomo.travaglini@arm.com while 1: 70613481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 70713481Sgiacomo.travaglini@arm.com if not token: 70813481Sgiacomo.travaglini@arm.com break 70913481Sgiacomo.travaglini@arm.com 71013481Sgiacomo.travaglini@arm.com # Get the next token. 71113481Sgiacomo.travaglini@arm.com self.current_token = token 71213481Sgiacomo.travaglini@arm.com 71313481Sgiacomo.travaglini@arm.com # Dispatch on the next token type. 71413481Sgiacomo.travaglini@arm.com if token.token_type == _INTERNAL_TOKEN: 71513481Sgiacomo.travaglini@arm.com if token.name == _NAMESPACE_POP: 71613481Sgiacomo.travaglini@arm.com self.namespace_stack.pop() 71713481Sgiacomo.travaglini@arm.com continue 71813481Sgiacomo.travaglini@arm.com 71913481Sgiacomo.travaglini@arm.com try: 72013481Sgiacomo.travaglini@arm.com result = self._GenerateOne(token) 72113481Sgiacomo.travaglini@arm.com if result is not None: 72213481Sgiacomo.travaglini@arm.com yield result 72313481Sgiacomo.travaglini@arm.com except: 72413481Sgiacomo.travaglini@arm.com self.HandleError('exception', token) 72513481Sgiacomo.travaglini@arm.com raise 72613481Sgiacomo.travaglini@arm.com 72713481Sgiacomo.travaglini@arm.com def _CreateVariable(self, pos_token, name, type_name, type_modifiers, 72813481Sgiacomo.travaglini@arm.com ref_pointer_name_seq, templated_types, value=None): 72913481Sgiacomo.travaglini@arm.com reference = '&' in ref_pointer_name_seq 73013481Sgiacomo.travaglini@arm.com pointer = '*' in ref_pointer_name_seq 73113481Sgiacomo.travaglini@arm.com array = '[' in ref_pointer_name_seq 73213481Sgiacomo.travaglini@arm.com var_type = Type(pos_token.start, pos_token.end, type_name, 73313481Sgiacomo.travaglini@arm.com templated_types, type_modifiers, 73413481Sgiacomo.travaglini@arm.com reference, pointer, array) 73513481Sgiacomo.travaglini@arm.com return VariableDeclaration(pos_token.start, pos_token.end, 73613481Sgiacomo.travaglini@arm.com name, var_type, value, self.namespace_stack) 73713481Sgiacomo.travaglini@arm.com 73813481Sgiacomo.travaglini@arm.com def _GenerateOne(self, token): 73913481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.NAME: 74013481Sgiacomo.travaglini@arm.com if (keywords.IsKeyword(token.name) and 74113481Sgiacomo.travaglini@arm.com not keywords.IsBuiltinType(token.name)): 74213481Sgiacomo.travaglini@arm.com method = getattr(self, 'handle_' + token.name) 74313481Sgiacomo.travaglini@arm.com return method() 74413481Sgiacomo.travaglini@arm.com elif token.name == self.in_class_name_only: 74513481Sgiacomo.travaglini@arm.com # The token name is the same as the class, must be a ctor if 74613481Sgiacomo.travaglini@arm.com # there is a paren. Otherwise, it's the return type. 74713481Sgiacomo.travaglini@arm.com # Peek ahead to get the next token to figure out which. 74813481Sgiacomo.travaglini@arm.com next = self._GetNextToken() 74913481Sgiacomo.travaglini@arm.com self._AddBackToken(next) 75013481Sgiacomo.travaglini@arm.com if next.token_type == tokenize.SYNTAX and next.name == '(': 75113481Sgiacomo.travaglini@arm.com return self._GetMethod([token], FUNCTION_CTOR, None, True) 75213481Sgiacomo.travaglini@arm.com # Fall through--handle like any other method. 75313481Sgiacomo.travaglini@arm.com 75413481Sgiacomo.travaglini@arm.com # Handle data or function declaration/definition. 75513481Sgiacomo.travaglini@arm.com syntax = tokenize.SYNTAX 75613481Sgiacomo.travaglini@arm.com temp_tokens, last_token = \ 75713481Sgiacomo.travaglini@arm.com self._GetVarTokensUpTo(syntax, '(', ';', '{', '[') 75813481Sgiacomo.travaglini@arm.com temp_tokens.insert(0, token) 75913481Sgiacomo.travaglini@arm.com if last_token.name == '(': 76013481Sgiacomo.travaglini@arm.com # If there is an assignment before the paren, 76113481Sgiacomo.travaglini@arm.com # this is an expression, not a method. 76213481Sgiacomo.travaglini@arm.com expr = bool([e for e in temp_tokens if e.name == '=']) 76313481Sgiacomo.travaglini@arm.com if expr: 76413481Sgiacomo.travaglini@arm.com new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';') 76513481Sgiacomo.travaglini@arm.com temp_tokens.append(last_token) 76613481Sgiacomo.travaglini@arm.com temp_tokens.extend(new_temp) 76713481Sgiacomo.travaglini@arm.com last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0) 76813481Sgiacomo.travaglini@arm.com 76913481Sgiacomo.travaglini@arm.com if last_token.name == '[': 77013481Sgiacomo.travaglini@arm.com # Handle array, this isn't a method, unless it's an operator. 77113481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): keep the size somewhere. 77213481Sgiacomo.travaglini@arm.com # unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']') 77313481Sgiacomo.travaglini@arm.com temp_tokens.append(last_token) 77413481Sgiacomo.travaglini@arm.com if temp_tokens[-2].name == 'operator': 77513481Sgiacomo.travaglini@arm.com temp_tokens.append(self._GetNextToken()) 77613481Sgiacomo.travaglini@arm.com else: 77713481Sgiacomo.travaglini@arm.com temp_tokens2, last_token = \ 77813481Sgiacomo.travaglini@arm.com self._GetVarTokensUpTo(tokenize.SYNTAX, ';') 77913481Sgiacomo.travaglini@arm.com temp_tokens.extend(temp_tokens2) 78013481Sgiacomo.travaglini@arm.com 78113481Sgiacomo.travaglini@arm.com if last_token.name == ';': 78213481Sgiacomo.travaglini@arm.com # Handle data, this isn't a method. 78313481Sgiacomo.travaglini@arm.com parts = self.converter.DeclarationToParts(temp_tokens, True) 78413481Sgiacomo.travaglini@arm.com (name, type_name, templated_types, modifiers, default, 78513481Sgiacomo.travaglini@arm.com unused_other_tokens) = parts 78613481Sgiacomo.travaglini@arm.com 78713481Sgiacomo.travaglini@arm.com t0 = temp_tokens[0] 78813481Sgiacomo.travaglini@arm.com names = [t.name for t in temp_tokens] 78913481Sgiacomo.travaglini@arm.com if templated_types: 79013481Sgiacomo.travaglini@arm.com start, end = self.converter.GetTemplateIndices(names) 79113481Sgiacomo.travaglini@arm.com names = names[:start] + names[end:] 79213481Sgiacomo.travaglini@arm.com default = ''.join([t.name for t in default]) 79313481Sgiacomo.travaglini@arm.com return self._CreateVariable(t0, name, type_name, modifiers, 79413481Sgiacomo.travaglini@arm.com names, templated_types, default) 79513481Sgiacomo.travaglini@arm.com if last_token.name == '{': 79613481Sgiacomo.travaglini@arm.com self._AddBackTokens(temp_tokens[1:]) 79713481Sgiacomo.travaglini@arm.com self._AddBackToken(last_token) 79813481Sgiacomo.travaglini@arm.com method_name = temp_tokens[0].name 79913481Sgiacomo.travaglini@arm.com method = getattr(self, 'handle_' + method_name, None) 80013481Sgiacomo.travaglini@arm.com if not method: 80113481Sgiacomo.travaglini@arm.com # Must be declaring a variable. 80213481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle the declaration. 80313481Sgiacomo.travaglini@arm.com return None 80413481Sgiacomo.travaglini@arm.com return method() 80513481Sgiacomo.travaglini@arm.com return self._GetMethod(temp_tokens, 0, None, False) 80613481Sgiacomo.travaglini@arm.com elif token.token_type == tokenize.SYNTAX: 80713481Sgiacomo.travaglini@arm.com if token.name == '~' and self.in_class: 80813481Sgiacomo.travaglini@arm.com # Must be a dtor (probably not in method body). 80913481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 81013481Sgiacomo.travaglini@arm.com # self.in_class can contain A::Name, but the dtor will only 81113481Sgiacomo.travaglini@arm.com # be Name. Make sure to compare against the right value. 81213481Sgiacomo.travaglini@arm.com if (token.token_type == tokenize.NAME and 81313481Sgiacomo.travaglini@arm.com token.name == self.in_class_name_only): 81413481Sgiacomo.travaglini@arm.com return self._GetMethod([token], FUNCTION_DTOR, None, True) 81513481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle a lot more syntax. 81613481Sgiacomo.travaglini@arm.com elif token.token_type == tokenize.PREPROCESSOR: 81713481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle more preprocessor directives. 81813481Sgiacomo.travaglini@arm.com # token starts with a #, so remove it and strip whitespace. 81913481Sgiacomo.travaglini@arm.com name = token.name[1:].lstrip() 82013481Sgiacomo.travaglini@arm.com if name.startswith('include'): 82113481Sgiacomo.travaglini@arm.com # Remove "include". 82213481Sgiacomo.travaglini@arm.com name = name[7:].strip() 82313481Sgiacomo.travaglini@arm.com assert name 82413481Sgiacomo.travaglini@arm.com # Handle #include \<newline> "header-on-second-line.h". 82513481Sgiacomo.travaglini@arm.com if name.startswith('\\'): 82613481Sgiacomo.travaglini@arm.com name = name[1:].strip() 82713481Sgiacomo.travaglini@arm.com assert name[0] in '<"', token 82813481Sgiacomo.travaglini@arm.com assert name[-1] in '>"', token 82913481Sgiacomo.travaglini@arm.com system = name[0] == '<' 83013481Sgiacomo.travaglini@arm.com filename = name[1:-1] 83113481Sgiacomo.travaglini@arm.com return Include(token.start, token.end, filename, system) 83213481Sgiacomo.travaglini@arm.com if name.startswith('define'): 83313481Sgiacomo.travaglini@arm.com # Remove "define". 83413481Sgiacomo.travaglini@arm.com name = name[6:].strip() 83513481Sgiacomo.travaglini@arm.com assert name 83613481Sgiacomo.travaglini@arm.com value = '' 83713481Sgiacomo.travaglini@arm.com for i, c in enumerate(name): 83813481Sgiacomo.travaglini@arm.com if c.isspace(): 83913481Sgiacomo.travaglini@arm.com value = name[i:].lstrip() 84013481Sgiacomo.travaglini@arm.com name = name[:i] 84113481Sgiacomo.travaglini@arm.com break 84213481Sgiacomo.travaglini@arm.com return Define(token.start, token.end, name, value) 84313481Sgiacomo.travaglini@arm.com if name.startswith('if') and name[2:3].isspace(): 84413481Sgiacomo.travaglini@arm.com condition = name[3:].strip() 84513481Sgiacomo.travaglini@arm.com if condition.startswith('0') or condition.startswith('(0)'): 84613481Sgiacomo.travaglini@arm.com self._SkipIf0Blocks() 84713481Sgiacomo.travaglini@arm.com return None 84813481Sgiacomo.travaglini@arm.com 84913481Sgiacomo.travaglini@arm.com def _GetTokensUpTo(self, expected_token_type, expected_token): 85013481Sgiacomo.travaglini@arm.com return self._GetVarTokensUpTo(expected_token_type, expected_token)[0] 85113481Sgiacomo.travaglini@arm.com 85213481Sgiacomo.travaglini@arm.com def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens): 85313481Sgiacomo.travaglini@arm.com last_token = self._GetNextToken() 85413481Sgiacomo.travaglini@arm.com tokens = [] 85513481Sgiacomo.travaglini@arm.com while (last_token.token_type != expected_token_type or 85613481Sgiacomo.travaglini@arm.com last_token.name not in expected_tokens): 85713481Sgiacomo.travaglini@arm.com tokens.append(last_token) 85813481Sgiacomo.travaglini@arm.com last_token = self._GetNextToken() 85913481Sgiacomo.travaglini@arm.com return tokens, last_token 86013481Sgiacomo.travaglini@arm.com 86113481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary. 86213481Sgiacomo.travaglini@arm.com def _IgnoreUpTo(self, token_type, token): 86313481Sgiacomo.travaglini@arm.com unused_tokens = self._GetTokensUpTo(token_type, token) 86413481Sgiacomo.travaglini@arm.com 86513481Sgiacomo.travaglini@arm.com def _SkipIf0Blocks(self): 86613481Sgiacomo.travaglini@arm.com count = 1 86713481Sgiacomo.travaglini@arm.com while 1: 86813481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 86913481Sgiacomo.travaglini@arm.com if token.token_type != tokenize.PREPROCESSOR: 87013481Sgiacomo.travaglini@arm.com continue 87113481Sgiacomo.travaglini@arm.com 87213481Sgiacomo.travaglini@arm.com name = token.name[1:].lstrip() 87313481Sgiacomo.travaglini@arm.com if name.startswith('endif'): 87413481Sgiacomo.travaglini@arm.com count -= 1 87513481Sgiacomo.travaglini@arm.com if count == 0: 87613481Sgiacomo.travaglini@arm.com break 87713481Sgiacomo.travaglini@arm.com elif name.startswith('if'): 87813481Sgiacomo.travaglini@arm.com count += 1 87913481Sgiacomo.travaglini@arm.com 88013481Sgiacomo.travaglini@arm.com def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None): 88113481Sgiacomo.travaglini@arm.com if GetNextToken is None: 88213481Sgiacomo.travaglini@arm.com GetNextToken = self._GetNextToken 88313481Sgiacomo.travaglini@arm.com # Assumes the current token is open_paren and we will consume 88413481Sgiacomo.travaglini@arm.com # and return up to the close_paren. 88513481Sgiacomo.travaglini@arm.com count = 1 88613481Sgiacomo.travaglini@arm.com token = GetNextToken() 88713481Sgiacomo.travaglini@arm.com while 1: 88813481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.SYNTAX: 88913481Sgiacomo.travaglini@arm.com if token.name == open_paren: 89013481Sgiacomo.travaglini@arm.com count += 1 89113481Sgiacomo.travaglini@arm.com elif token.name == close_paren: 89213481Sgiacomo.travaglini@arm.com count -= 1 89313481Sgiacomo.travaglini@arm.com if count == 0: 89413481Sgiacomo.travaglini@arm.com break 89513481Sgiacomo.travaglini@arm.com yield token 89613481Sgiacomo.travaglini@arm.com token = GetNextToken() 89713481Sgiacomo.travaglini@arm.com yield token 89813481Sgiacomo.travaglini@arm.com 89913481Sgiacomo.travaglini@arm.com def _GetParameters(self): 90013481Sgiacomo.travaglini@arm.com return self._GetMatchingChar('(', ')') 90113481Sgiacomo.travaglini@arm.com 90213481Sgiacomo.travaglini@arm.com def GetScope(self): 90313481Sgiacomo.travaglini@arm.com return self._GetMatchingChar('{', '}') 90413481Sgiacomo.travaglini@arm.com 90513481Sgiacomo.travaglini@arm.com def _GetNextToken(self): 90613481Sgiacomo.travaglini@arm.com if self.token_queue: 90713481Sgiacomo.travaglini@arm.com return self.token_queue.pop() 90813481Sgiacomo.travaglini@arm.com return next(self.tokens) 90913481Sgiacomo.travaglini@arm.com 91013481Sgiacomo.travaglini@arm.com def _AddBackToken(self, token): 91113481Sgiacomo.travaglini@arm.com if token.whence == tokenize.WHENCE_STREAM: 91213481Sgiacomo.travaglini@arm.com token.whence = tokenize.WHENCE_QUEUE 91313481Sgiacomo.travaglini@arm.com self.token_queue.insert(0, token) 91413481Sgiacomo.travaglini@arm.com else: 91513481Sgiacomo.travaglini@arm.com assert token.whence == tokenize.WHENCE_QUEUE, token 91613481Sgiacomo.travaglini@arm.com self.token_queue.append(token) 91713481Sgiacomo.travaglini@arm.com 91813481Sgiacomo.travaglini@arm.com def _AddBackTokens(self, tokens): 91913481Sgiacomo.travaglini@arm.com if tokens: 92013481Sgiacomo.travaglini@arm.com if tokens[-1].whence == tokenize.WHENCE_STREAM: 92113481Sgiacomo.travaglini@arm.com for token in tokens: 92213481Sgiacomo.travaglini@arm.com token.whence = tokenize.WHENCE_QUEUE 92313481Sgiacomo.travaglini@arm.com self.token_queue[:0] = reversed(tokens) 92413481Sgiacomo.travaglini@arm.com else: 92513481Sgiacomo.travaglini@arm.com assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens 92613481Sgiacomo.travaglini@arm.com self.token_queue.extend(reversed(tokens)) 92713481Sgiacomo.travaglini@arm.com 92813481Sgiacomo.travaglini@arm.com def GetName(self, seq=None): 92913481Sgiacomo.travaglini@arm.com """Returns ([tokens], next_token_info).""" 93013481Sgiacomo.travaglini@arm.com GetNextToken = self._GetNextToken 93113481Sgiacomo.travaglini@arm.com if seq is not None: 93213481Sgiacomo.travaglini@arm.com it = iter(seq) 93313481Sgiacomo.travaglini@arm.com GetNextToken = lambda: next(it) 93413481Sgiacomo.travaglini@arm.com next_token = GetNextToken() 93513481Sgiacomo.travaglini@arm.com tokens = [] 93613481Sgiacomo.travaglini@arm.com last_token_was_name = False 93713481Sgiacomo.travaglini@arm.com while (next_token.token_type == tokenize.NAME or 93813481Sgiacomo.travaglini@arm.com (next_token.token_type == tokenize.SYNTAX and 93913481Sgiacomo.travaglini@arm.com next_token.name in ('::', '<'))): 94013481Sgiacomo.travaglini@arm.com # Two NAMEs in a row means the identifier should terminate. 94113481Sgiacomo.travaglini@arm.com # It's probably some sort of variable declaration. 94213481Sgiacomo.travaglini@arm.com if last_token_was_name and next_token.token_type == tokenize.NAME: 94313481Sgiacomo.travaglini@arm.com break 94413481Sgiacomo.travaglini@arm.com last_token_was_name = next_token.token_type == tokenize.NAME 94513481Sgiacomo.travaglini@arm.com tokens.append(next_token) 94613481Sgiacomo.travaglini@arm.com # Handle templated names. 94713481Sgiacomo.travaglini@arm.com if next_token.name == '<': 94813481Sgiacomo.travaglini@arm.com tokens.extend(self._GetMatchingChar('<', '>', GetNextToken)) 94913481Sgiacomo.travaglini@arm.com last_token_was_name = True 95013481Sgiacomo.travaglini@arm.com next_token = GetNextToken() 95113481Sgiacomo.travaglini@arm.com return tokens, next_token 95213481Sgiacomo.travaglini@arm.com 95313481Sgiacomo.travaglini@arm.com def GetMethod(self, modifiers, templated_types): 95413481Sgiacomo.travaglini@arm.com return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') 95513481Sgiacomo.travaglini@arm.com assert len(return_type_and_name) >= 1 95613481Sgiacomo.travaglini@arm.com return self._GetMethod(return_type_and_name, modifiers, templated_types, 95713481Sgiacomo.travaglini@arm.com False) 95813481Sgiacomo.travaglini@arm.com 95913481Sgiacomo.travaglini@arm.com def _GetMethod(self, return_type_and_name, modifiers, templated_types, 96013481Sgiacomo.travaglini@arm.com get_paren): 96113481Sgiacomo.travaglini@arm.com template_portion = None 96213481Sgiacomo.travaglini@arm.com if get_paren: 96313481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 96413481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 96513481Sgiacomo.travaglini@arm.com if token.name == '<': 96613481Sgiacomo.travaglini@arm.com # Handle templatized dtors. 96713481Sgiacomo.travaglini@arm.com template_portion = [token] 96813481Sgiacomo.travaglini@arm.com template_portion.extend(self._GetMatchingChar('<', '>')) 96913481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 97013481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 97113481Sgiacomo.travaglini@arm.com assert token.name == '(', token 97213481Sgiacomo.travaglini@arm.com 97313481Sgiacomo.travaglini@arm.com name = return_type_and_name.pop() 97413481Sgiacomo.travaglini@arm.com # Handle templatized ctors. 97513481Sgiacomo.travaglini@arm.com if name.name == '>': 97613481Sgiacomo.travaglini@arm.com index = 1 97713481Sgiacomo.travaglini@arm.com while return_type_and_name[index].name != '<': 97813481Sgiacomo.travaglini@arm.com index += 1 97913481Sgiacomo.travaglini@arm.com template_portion = return_type_and_name[index:] + [name] 98013481Sgiacomo.travaglini@arm.com del return_type_and_name[index:] 98113481Sgiacomo.travaglini@arm.com name = return_type_and_name.pop() 98213481Sgiacomo.travaglini@arm.com elif name.name == ']': 98313481Sgiacomo.travaglini@arm.com rt = return_type_and_name 98413481Sgiacomo.travaglini@arm.com assert rt[-1].name == '[', return_type_and_name 98513481Sgiacomo.travaglini@arm.com assert rt[-2].name == 'operator', return_type_and_name 98613481Sgiacomo.travaglini@arm.com name_seq = return_type_and_name[-2:] 98713481Sgiacomo.travaglini@arm.com del return_type_and_name[-2:] 98813481Sgiacomo.travaglini@arm.com name = tokenize.Token(tokenize.NAME, 'operator[]', 98913481Sgiacomo.travaglini@arm.com name_seq[0].start, name.end) 99013481Sgiacomo.travaglini@arm.com # Get the open paren so _GetParameters() below works. 99113481Sgiacomo.travaglini@arm.com unused_open_paren = self._GetNextToken() 99213481Sgiacomo.travaglini@arm.com 99313481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): store template_portion. 99413481Sgiacomo.travaglini@arm.com return_type = return_type_and_name 99513481Sgiacomo.travaglini@arm.com indices = name 99613481Sgiacomo.travaglini@arm.com if return_type: 99713481Sgiacomo.travaglini@arm.com indices = return_type[0] 99813481Sgiacomo.travaglini@arm.com 99913481Sgiacomo.travaglini@arm.com # Force ctor for templatized ctors. 100013481Sgiacomo.travaglini@arm.com if name.name == self.in_class and not modifiers: 100113481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_CTOR 100213481Sgiacomo.travaglini@arm.com parameters = list(self._GetParameters()) 100313481Sgiacomo.travaglini@arm.com del parameters[-1] # Remove trailing ')'. 100413481Sgiacomo.travaglini@arm.com 100513481Sgiacomo.travaglini@arm.com # Handling operator() is especially weird. 100613481Sgiacomo.travaglini@arm.com if name.name == 'operator' and not parameters: 100713481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 100813481Sgiacomo.travaglini@arm.com assert token.name == '(', token 100913481Sgiacomo.travaglini@arm.com parameters = list(self._GetParameters()) 101013481Sgiacomo.travaglini@arm.com del parameters[-1] # Remove trailing ')'. 101113481Sgiacomo.travaglini@arm.com 101213481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 101313481Sgiacomo.travaglini@arm.com while token.token_type == tokenize.NAME: 101413481Sgiacomo.travaglini@arm.com modifier_token = token 101513481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 101613481Sgiacomo.travaglini@arm.com if modifier_token.name == 'const': 101713481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_CONST 101813481Sgiacomo.travaglini@arm.com elif modifier_token.name == '__attribute__': 101913481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle more __attribute__ details. 102013481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_ATTRIBUTE 102113481Sgiacomo.travaglini@arm.com assert token.name == '(', token 102213481Sgiacomo.travaglini@arm.com # Consume everything between the (parens). 102313481Sgiacomo.travaglini@arm.com unused_tokens = list(self._GetMatchingChar('(', ')')) 102413481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 102513481Sgiacomo.travaglini@arm.com elif modifier_token.name == 'throw': 102613481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_THROW 102713481Sgiacomo.travaglini@arm.com assert token.name == '(', token 102813481Sgiacomo.travaglini@arm.com # Consume everything between the (parens). 102913481Sgiacomo.travaglini@arm.com unused_tokens = list(self._GetMatchingChar('(', ')')) 103013481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 103113481Sgiacomo.travaglini@arm.com elif modifier_token.name == 'override': 103213481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_OVERRIDE 103313481Sgiacomo.travaglini@arm.com elif modifier_token.name == modifier_token.name.upper(): 103413481Sgiacomo.travaglini@arm.com # HACK(nnorwitz): assume that all upper-case names 103513481Sgiacomo.travaglini@arm.com # are some macro we aren't expanding. 103613481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_UNKNOWN_ANNOTATION 103713481Sgiacomo.travaglini@arm.com else: 103813481Sgiacomo.travaglini@arm.com self.HandleError('unexpected token', modifier_token) 103913481Sgiacomo.travaglini@arm.com 104013481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 104113481Sgiacomo.travaglini@arm.com # Handle ctor initializers. 104213481Sgiacomo.travaglini@arm.com if token.name == ':': 104313481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): anything else to handle for initializer list? 104413481Sgiacomo.travaglini@arm.com while token.name != ';' and token.name != '{': 104513481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 104613481Sgiacomo.travaglini@arm.com 104713481Sgiacomo.travaglini@arm.com # Handle pointer to functions that are really data but look 104813481Sgiacomo.travaglini@arm.com # like method declarations. 104913481Sgiacomo.travaglini@arm.com if token.name == '(': 105013481Sgiacomo.travaglini@arm.com if parameters[0].name == '*': 105113481Sgiacomo.travaglini@arm.com # name contains the return type. 105213481Sgiacomo.travaglini@arm.com name = parameters.pop() 105313481Sgiacomo.travaglini@arm.com # parameters contains the name of the data. 105413481Sgiacomo.travaglini@arm.com modifiers = [p.name for p in parameters] 105513481Sgiacomo.travaglini@arm.com # Already at the ( to open the parameter list. 105613481Sgiacomo.travaglini@arm.com function_parameters = list(self._GetMatchingChar('(', ')')) 105713481Sgiacomo.travaglini@arm.com del function_parameters[-1] # Remove trailing ')'. 105813481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): store the function_parameters. 105913481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 106013481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 106113481Sgiacomo.travaglini@arm.com assert token.name == ';', token 106213481Sgiacomo.travaglini@arm.com return self._CreateVariable(indices, name.name, indices.name, 106313481Sgiacomo.travaglini@arm.com modifiers, '', None) 106413481Sgiacomo.travaglini@arm.com # At this point, we got something like: 106513481Sgiacomo.travaglini@arm.com # return_type (type::*name_)(params); 106613481Sgiacomo.travaglini@arm.com # This is a data member called name_ that is a function pointer. 106713481Sgiacomo.travaglini@arm.com # With this code: void (sq_type::*field_)(string&); 106813481Sgiacomo.travaglini@arm.com # We get: name=void return_type=[] parameters=sq_type ... field_ 106913481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): is return_type always empty? 107013481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): this isn't even close to being correct. 107113481Sgiacomo.travaglini@arm.com # Just put in something so we don't crash and can move on. 107213481Sgiacomo.travaglini@arm.com real_name = parameters[-1] 107313481Sgiacomo.travaglini@arm.com modifiers = [p.name for p in self._GetParameters()] 107413481Sgiacomo.travaglini@arm.com del modifiers[-1] # Remove trailing ')'. 107513481Sgiacomo.travaglini@arm.com return self._CreateVariable(indices, real_name.name, indices.name, 107613481Sgiacomo.travaglini@arm.com modifiers, '', None) 107713481Sgiacomo.travaglini@arm.com 107813481Sgiacomo.travaglini@arm.com if token.name == '{': 107913481Sgiacomo.travaglini@arm.com body = list(self.GetScope()) 108013481Sgiacomo.travaglini@arm.com del body[-1] # Remove trailing '}'. 108113481Sgiacomo.travaglini@arm.com else: 108213481Sgiacomo.travaglini@arm.com body = None 108313481Sgiacomo.travaglini@arm.com if token.name == '=': 108413481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 108513481Sgiacomo.travaglini@arm.com 108613481Sgiacomo.travaglini@arm.com if token.name == 'default' or token.name == 'delete': 108713481Sgiacomo.travaglini@arm.com # Ignore explicitly defaulted and deleted special members 108813481Sgiacomo.travaglini@arm.com # in C++11. 108913481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 109013481Sgiacomo.travaglini@arm.com else: 109113481Sgiacomo.travaglini@arm.com # Handle pure-virtual declarations. 109213481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.CONSTANT, token 109313481Sgiacomo.travaglini@arm.com assert token.name == '0', token 109413481Sgiacomo.travaglini@arm.com modifiers |= FUNCTION_PURE_VIRTUAL 109513481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 109613481Sgiacomo.travaglini@arm.com 109713481Sgiacomo.travaglini@arm.com if token.name == '[': 109813481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): store tokens and improve parsing. 109913481Sgiacomo.travaglini@arm.com # template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N]; 110013481Sgiacomo.travaglini@arm.com tokens = list(self._GetMatchingChar('[', ']')) 110113481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 110213481Sgiacomo.travaglini@arm.com 110313481Sgiacomo.travaglini@arm.com assert token.name == ';', (token, return_type_and_name, parameters) 110413481Sgiacomo.travaglini@arm.com 110513481Sgiacomo.travaglini@arm.com # Looks like we got a method, not a function. 110613481Sgiacomo.travaglini@arm.com if len(return_type) > 2 and return_type[-1].name == '::': 110713481Sgiacomo.travaglini@arm.com return_type, in_class = \ 110813481Sgiacomo.travaglini@arm.com self._GetReturnTypeAndClassName(return_type) 110913481Sgiacomo.travaglini@arm.com return Method(indices.start, indices.end, name.name, in_class, 111013481Sgiacomo.travaglini@arm.com return_type, parameters, modifiers, templated_types, 111113481Sgiacomo.travaglini@arm.com body, self.namespace_stack) 111213481Sgiacomo.travaglini@arm.com return Function(indices.start, indices.end, name.name, return_type, 111313481Sgiacomo.travaglini@arm.com parameters, modifiers, templated_types, body, 111413481Sgiacomo.travaglini@arm.com self.namespace_stack) 111513481Sgiacomo.travaglini@arm.com 111613481Sgiacomo.travaglini@arm.com def _GetReturnTypeAndClassName(self, token_seq): 111713481Sgiacomo.travaglini@arm.com # Splitting the return type from the class name in a method 111813481Sgiacomo.travaglini@arm.com # can be tricky. For example, Return::Type::Is::Hard::To::Find(). 111913481Sgiacomo.travaglini@arm.com # Where is the return type and where is the class name? 112013481Sgiacomo.travaglini@arm.com # The heuristic used is to pull the last name as the class name. 112113481Sgiacomo.travaglini@arm.com # This includes all the templated type info. 112213481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): if there is only One name like in the 112313481Sgiacomo.travaglini@arm.com # example above, punt and assume the last bit is the class name. 112413481Sgiacomo.travaglini@arm.com 112513481Sgiacomo.travaglini@arm.com # Ignore a :: prefix, if exists so we can find the first real name. 112613481Sgiacomo.travaglini@arm.com i = 0 112713481Sgiacomo.travaglini@arm.com if token_seq[0].name == '::': 112813481Sgiacomo.travaglini@arm.com i = 1 112913481Sgiacomo.travaglini@arm.com # Ignore a :: suffix, if exists. 113013481Sgiacomo.travaglini@arm.com end = len(token_seq) - 1 113113481Sgiacomo.travaglini@arm.com if token_seq[end-1].name == '::': 113213481Sgiacomo.travaglini@arm.com end -= 1 113313481Sgiacomo.travaglini@arm.com 113413481Sgiacomo.travaglini@arm.com # Make a copy of the sequence so we can append a sentinel 113513481Sgiacomo.travaglini@arm.com # value. This is required for GetName will has to have some 113613481Sgiacomo.travaglini@arm.com # terminating condition beyond the last name. 113713481Sgiacomo.travaglini@arm.com seq_copy = token_seq[i:end] 113813481Sgiacomo.travaglini@arm.com seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0)) 113913481Sgiacomo.travaglini@arm.com names = [] 114013481Sgiacomo.travaglini@arm.com while i < end: 114113481Sgiacomo.travaglini@arm.com # Iterate through the sequence parsing out each name. 114213481Sgiacomo.travaglini@arm.com new_name, next = self.GetName(seq_copy[i:]) 114313481Sgiacomo.travaglini@arm.com assert new_name, 'Got empty new_name, next=%s' % next 114413481Sgiacomo.travaglini@arm.com # We got a pointer or ref. Add it to the name. 114513481Sgiacomo.travaglini@arm.com if next and next.token_type == tokenize.SYNTAX: 114613481Sgiacomo.travaglini@arm.com new_name.append(next) 114713481Sgiacomo.travaglini@arm.com names.append(new_name) 114813481Sgiacomo.travaglini@arm.com i += len(new_name) 114913481Sgiacomo.travaglini@arm.com 115013481Sgiacomo.travaglini@arm.com # Now that we have the names, it's time to undo what we did. 115113481Sgiacomo.travaglini@arm.com 115213481Sgiacomo.travaglini@arm.com # Remove the sentinel value. 115313481Sgiacomo.travaglini@arm.com names[-1].pop() 115413481Sgiacomo.travaglini@arm.com # Flatten the token sequence for the return type. 115513481Sgiacomo.travaglini@arm.com return_type = [e for seq in names[:-1] for e in seq] 115613481Sgiacomo.travaglini@arm.com # The class name is the last name. 115713481Sgiacomo.travaglini@arm.com class_name = names[-1] 115813481Sgiacomo.travaglini@arm.com return return_type, class_name 115913481Sgiacomo.travaglini@arm.com 116013481Sgiacomo.travaglini@arm.com def handle_bool(self): 116113481Sgiacomo.travaglini@arm.com pass 116213481Sgiacomo.travaglini@arm.com 116313481Sgiacomo.travaglini@arm.com def handle_char(self): 116413481Sgiacomo.travaglini@arm.com pass 116513481Sgiacomo.travaglini@arm.com 116613481Sgiacomo.travaglini@arm.com def handle_int(self): 116713481Sgiacomo.travaglini@arm.com pass 116813481Sgiacomo.travaglini@arm.com 116913481Sgiacomo.travaglini@arm.com def handle_long(self): 117013481Sgiacomo.travaglini@arm.com pass 117113481Sgiacomo.travaglini@arm.com 117213481Sgiacomo.travaglini@arm.com def handle_short(self): 117313481Sgiacomo.travaglini@arm.com pass 117413481Sgiacomo.travaglini@arm.com 117513481Sgiacomo.travaglini@arm.com def handle_double(self): 117613481Sgiacomo.travaglini@arm.com pass 117713481Sgiacomo.travaglini@arm.com 117813481Sgiacomo.travaglini@arm.com def handle_float(self): 117913481Sgiacomo.travaglini@arm.com pass 118013481Sgiacomo.travaglini@arm.com 118113481Sgiacomo.travaglini@arm.com def handle_void(self): 118213481Sgiacomo.travaglini@arm.com pass 118313481Sgiacomo.travaglini@arm.com 118413481Sgiacomo.travaglini@arm.com def handle_wchar_t(self): 118513481Sgiacomo.travaglini@arm.com pass 118613481Sgiacomo.travaglini@arm.com 118713481Sgiacomo.travaglini@arm.com def handle_unsigned(self): 118813481Sgiacomo.travaglini@arm.com pass 118913481Sgiacomo.travaglini@arm.com 119013481Sgiacomo.travaglini@arm.com def handle_signed(self): 119113481Sgiacomo.travaglini@arm.com pass 119213481Sgiacomo.travaglini@arm.com 119313481Sgiacomo.travaglini@arm.com def _GetNestedType(self, ctor): 119413481Sgiacomo.travaglini@arm.com name = None 119513481Sgiacomo.travaglini@arm.com name_tokens, token = self.GetName() 119613481Sgiacomo.travaglini@arm.com if name_tokens: 119713481Sgiacomo.travaglini@arm.com name = ''.join([t.name for t in name_tokens]) 119813481Sgiacomo.travaglini@arm.com 119913481Sgiacomo.travaglini@arm.com # Handle forward declarations. 120013481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.SYNTAX and token.name == ';': 120113481Sgiacomo.travaglini@arm.com return ctor(token.start, token.end, name, None, 120213481Sgiacomo.travaglini@arm.com self.namespace_stack) 120313481Sgiacomo.travaglini@arm.com 120413481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.NAME and self._handling_typedef: 120513481Sgiacomo.travaglini@arm.com self._AddBackToken(token) 120613481Sgiacomo.travaglini@arm.com return ctor(token.start, token.end, name, None, 120713481Sgiacomo.travaglini@arm.com self.namespace_stack) 120813481Sgiacomo.travaglini@arm.com 120913481Sgiacomo.travaglini@arm.com # Must be the type declaration. 121013481Sgiacomo.travaglini@arm.com fields = list(self._GetMatchingChar('{', '}')) 121113481Sgiacomo.travaglini@arm.com del fields[-1] # Remove trailing '}'. 121213481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.SYNTAX and token.name == '{': 121313481Sgiacomo.travaglini@arm.com next = self._GetNextToken() 121413481Sgiacomo.travaglini@arm.com new_type = ctor(token.start, token.end, name, fields, 121513481Sgiacomo.travaglini@arm.com self.namespace_stack) 121613481Sgiacomo.travaglini@arm.com # A name means this is an anonymous type and the name 121713481Sgiacomo.travaglini@arm.com # is the variable declaration. 121813481Sgiacomo.travaglini@arm.com if next.token_type != tokenize.NAME: 121913481Sgiacomo.travaglini@arm.com return new_type 122013481Sgiacomo.travaglini@arm.com name = new_type 122113481Sgiacomo.travaglini@arm.com token = next 122213481Sgiacomo.travaglini@arm.com 122313481Sgiacomo.travaglini@arm.com # Must be variable declaration using the type prefixed with keyword. 122413481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.NAME, token 122513481Sgiacomo.travaglini@arm.com return self._CreateVariable(token, token.name, name, [], '', None) 122613481Sgiacomo.travaglini@arm.com 122713481Sgiacomo.travaglini@arm.com def handle_struct(self): 122813481Sgiacomo.travaglini@arm.com # Special case the handling typedef/aliasing of structs here. 122913481Sgiacomo.travaglini@arm.com # It would be a pain to handle in the class code. 123013481Sgiacomo.travaglini@arm.com name_tokens, var_token = self.GetName() 123113481Sgiacomo.travaglini@arm.com if name_tokens: 123213481Sgiacomo.travaglini@arm.com next_token = self._GetNextToken() 123313481Sgiacomo.travaglini@arm.com is_syntax = (var_token.token_type == tokenize.SYNTAX and 123413481Sgiacomo.travaglini@arm.com var_token.name[0] in '*&') 123513481Sgiacomo.travaglini@arm.com is_variable = (var_token.token_type == tokenize.NAME and 123613481Sgiacomo.travaglini@arm.com next_token.name == ';') 123713481Sgiacomo.travaglini@arm.com variable = var_token 123813481Sgiacomo.travaglini@arm.com if is_syntax and not is_variable: 123913481Sgiacomo.travaglini@arm.com variable = next_token 124013481Sgiacomo.travaglini@arm.com temp = self._GetNextToken() 124113481Sgiacomo.travaglini@arm.com if temp.token_type == tokenize.SYNTAX and temp.name == '(': 124213481Sgiacomo.travaglini@arm.com # Handle methods declared to return a struct. 124313481Sgiacomo.travaglini@arm.com t0 = name_tokens[0] 124413481Sgiacomo.travaglini@arm.com struct = tokenize.Token(tokenize.NAME, 'struct', 124513481Sgiacomo.travaglini@arm.com t0.start-7, t0.start-2) 124613481Sgiacomo.travaglini@arm.com type_and_name = [struct] 124713481Sgiacomo.travaglini@arm.com type_and_name.extend(name_tokens) 124813481Sgiacomo.travaglini@arm.com type_and_name.extend((var_token, next_token)) 124913481Sgiacomo.travaglini@arm.com return self._GetMethod(type_and_name, 0, None, False) 125013481Sgiacomo.travaglini@arm.com assert temp.name == ';', (temp, name_tokens, var_token) 125113481Sgiacomo.travaglini@arm.com if is_syntax or (is_variable and not self._handling_typedef): 125213481Sgiacomo.travaglini@arm.com modifiers = ['struct'] 125313481Sgiacomo.travaglini@arm.com type_name = ''.join([t.name for t in name_tokens]) 125413481Sgiacomo.travaglini@arm.com position = name_tokens[0] 125513481Sgiacomo.travaglini@arm.com return self._CreateVariable(position, variable.name, type_name, 125613481Sgiacomo.travaglini@arm.com modifiers, var_token.name, None) 125713481Sgiacomo.travaglini@arm.com name_tokens.extend((var_token, next_token)) 125813481Sgiacomo.travaglini@arm.com self._AddBackTokens(name_tokens) 125913481Sgiacomo.travaglini@arm.com else: 126013481Sgiacomo.travaglini@arm.com self._AddBackToken(var_token) 126113481Sgiacomo.travaglini@arm.com return self._GetClass(Struct, VISIBILITY_PUBLIC, None) 126213481Sgiacomo.travaglini@arm.com 126313481Sgiacomo.travaglini@arm.com def handle_union(self): 126413481Sgiacomo.travaglini@arm.com return self._GetNestedType(Union) 126513481Sgiacomo.travaglini@arm.com 126613481Sgiacomo.travaglini@arm.com def handle_enum(self): 126713481Sgiacomo.travaglini@arm.com return self._GetNestedType(Enum) 126813481Sgiacomo.travaglini@arm.com 126913481Sgiacomo.travaglini@arm.com def handle_auto(self): 127013481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): warn about using auto? Probably not since it 127113481Sgiacomo.travaglini@arm.com # will be reclaimed and useful for C++0x. 127213481Sgiacomo.travaglini@arm.com pass 127313481Sgiacomo.travaglini@arm.com 127413481Sgiacomo.travaglini@arm.com def handle_register(self): 127513481Sgiacomo.travaglini@arm.com pass 127613481Sgiacomo.travaglini@arm.com 127713481Sgiacomo.travaglini@arm.com def handle_const(self): 127813481Sgiacomo.travaglini@arm.com pass 127913481Sgiacomo.travaglini@arm.com 128013481Sgiacomo.travaglini@arm.com def handle_inline(self): 128113481Sgiacomo.travaglini@arm.com pass 128213481Sgiacomo.travaglini@arm.com 128313481Sgiacomo.travaglini@arm.com def handle_extern(self): 128413481Sgiacomo.travaglini@arm.com pass 128513481Sgiacomo.travaglini@arm.com 128613481Sgiacomo.travaglini@arm.com def handle_static(self): 128713481Sgiacomo.travaglini@arm.com pass 128813481Sgiacomo.travaglini@arm.com 128913481Sgiacomo.travaglini@arm.com def handle_virtual(self): 129013481Sgiacomo.travaglini@arm.com # What follows must be a method. 129113481Sgiacomo.travaglini@arm.com token = token2 = self._GetNextToken() 129213481Sgiacomo.travaglini@arm.com if token.name == 'inline': 129313481Sgiacomo.travaglini@arm.com # HACK(nnorwitz): handle inline dtors by ignoring 'inline'. 129413481Sgiacomo.travaglini@arm.com token2 = self._GetNextToken() 129513481Sgiacomo.travaglini@arm.com if token2.token_type == tokenize.SYNTAX and token2.name == '~': 129613481Sgiacomo.travaglini@arm.com return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None) 129713481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.NAME or token.name == '::', token 129813481Sgiacomo.travaglini@arm.com return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') # ) 129913481Sgiacomo.travaglini@arm.com return_type_and_name.insert(0, token) 130013481Sgiacomo.travaglini@arm.com if token2 is not token: 130113481Sgiacomo.travaglini@arm.com return_type_and_name.insert(1, token2) 130213481Sgiacomo.travaglini@arm.com return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL, 130313481Sgiacomo.travaglini@arm.com None, False) 130413481Sgiacomo.travaglini@arm.com 130513481Sgiacomo.travaglini@arm.com def handle_volatile(self): 130613481Sgiacomo.travaglini@arm.com pass 130713481Sgiacomo.travaglini@arm.com 130813481Sgiacomo.travaglini@arm.com def handle_mutable(self): 130913481Sgiacomo.travaglini@arm.com pass 131013481Sgiacomo.travaglini@arm.com 131113481Sgiacomo.travaglini@arm.com def handle_public(self): 131213481Sgiacomo.travaglini@arm.com assert self.in_class 131313481Sgiacomo.travaglini@arm.com self.visibility = VISIBILITY_PUBLIC 131413481Sgiacomo.travaglini@arm.com 131513481Sgiacomo.travaglini@arm.com def handle_protected(self): 131613481Sgiacomo.travaglini@arm.com assert self.in_class 131713481Sgiacomo.travaglini@arm.com self.visibility = VISIBILITY_PROTECTED 131813481Sgiacomo.travaglini@arm.com 131913481Sgiacomo.travaglini@arm.com def handle_private(self): 132013481Sgiacomo.travaglini@arm.com assert self.in_class 132113481Sgiacomo.travaglini@arm.com self.visibility = VISIBILITY_PRIVATE 132213481Sgiacomo.travaglini@arm.com 132313481Sgiacomo.travaglini@arm.com def handle_friend(self): 132413481Sgiacomo.travaglini@arm.com tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 132513481Sgiacomo.travaglini@arm.com assert tokens 132613481Sgiacomo.travaglini@arm.com t0 = tokens[0] 132713481Sgiacomo.travaglini@arm.com return Friend(t0.start, t0.end, tokens, self.namespace_stack) 132813481Sgiacomo.travaglini@arm.com 132913481Sgiacomo.travaglini@arm.com def handle_static_cast(self): 133013481Sgiacomo.travaglini@arm.com pass 133113481Sgiacomo.travaglini@arm.com 133213481Sgiacomo.travaglini@arm.com def handle_const_cast(self): 133313481Sgiacomo.travaglini@arm.com pass 133413481Sgiacomo.travaglini@arm.com 133513481Sgiacomo.travaglini@arm.com def handle_dynamic_cast(self): 133613481Sgiacomo.travaglini@arm.com pass 133713481Sgiacomo.travaglini@arm.com 133813481Sgiacomo.travaglini@arm.com def handle_reinterpret_cast(self): 133913481Sgiacomo.travaglini@arm.com pass 134013481Sgiacomo.travaglini@arm.com 134113481Sgiacomo.travaglini@arm.com def handle_new(self): 134213481Sgiacomo.travaglini@arm.com pass 134313481Sgiacomo.travaglini@arm.com 134413481Sgiacomo.travaglini@arm.com def handle_delete(self): 134513481Sgiacomo.travaglini@arm.com tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 134613481Sgiacomo.travaglini@arm.com assert tokens 134713481Sgiacomo.travaglini@arm.com return Delete(tokens[0].start, tokens[0].end, tokens) 134813481Sgiacomo.travaglini@arm.com 134913481Sgiacomo.travaglini@arm.com def handle_typedef(self): 135013481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 135113481Sgiacomo.travaglini@arm.com if (token.token_type == tokenize.NAME and 135213481Sgiacomo.travaglini@arm.com keywords.IsKeyword(token.name)): 135313481Sgiacomo.travaglini@arm.com # Token must be struct/enum/union/class. 135413481Sgiacomo.travaglini@arm.com method = getattr(self, 'handle_' + token.name) 135513481Sgiacomo.travaglini@arm.com self._handling_typedef = True 135613481Sgiacomo.travaglini@arm.com tokens = [method()] 135713481Sgiacomo.travaglini@arm.com self._handling_typedef = False 135813481Sgiacomo.travaglini@arm.com else: 135913481Sgiacomo.travaglini@arm.com tokens = [token] 136013481Sgiacomo.travaglini@arm.com 136113481Sgiacomo.travaglini@arm.com # Get the remainder of the typedef up to the semi-colon. 136213481Sgiacomo.travaglini@arm.com tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';')) 136313481Sgiacomo.travaglini@arm.com 136413481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): clean all this up. 136513481Sgiacomo.travaglini@arm.com assert tokens 136613481Sgiacomo.travaglini@arm.com name = tokens.pop() 136713481Sgiacomo.travaglini@arm.com indices = name 136813481Sgiacomo.travaglini@arm.com if tokens: 136913481Sgiacomo.travaglini@arm.com indices = tokens[0] 137013481Sgiacomo.travaglini@arm.com if not indices: 137113481Sgiacomo.travaglini@arm.com indices = token 137213481Sgiacomo.travaglini@arm.com if name.name == ')': 137313481Sgiacomo.travaglini@arm.com # HACK(nnorwitz): Handle pointers to functions "properly". 137413481Sgiacomo.travaglini@arm.com if (len(tokens) >= 4 and 137513481Sgiacomo.travaglini@arm.com tokens[1].name == '(' and tokens[2].name == '*'): 137613481Sgiacomo.travaglini@arm.com tokens.append(name) 137713481Sgiacomo.travaglini@arm.com name = tokens[3] 137813481Sgiacomo.travaglini@arm.com elif name.name == ']': 137913481Sgiacomo.travaglini@arm.com # HACK(nnorwitz): Handle arrays properly. 138013481Sgiacomo.travaglini@arm.com if len(tokens) >= 2: 138113481Sgiacomo.travaglini@arm.com tokens.append(name) 138213481Sgiacomo.travaglini@arm.com name = tokens[1] 138313481Sgiacomo.travaglini@arm.com new_type = tokens 138413481Sgiacomo.travaglini@arm.com if tokens and isinstance(tokens[0], tokenize.Token): 138513481Sgiacomo.travaglini@arm.com new_type = self.converter.ToType(tokens)[0] 138613481Sgiacomo.travaglini@arm.com return Typedef(indices.start, indices.end, name.name, 138713481Sgiacomo.travaglini@arm.com new_type, self.namespace_stack) 138813481Sgiacomo.travaglini@arm.com 138913481Sgiacomo.travaglini@arm.com def handle_typeid(self): 139013481Sgiacomo.travaglini@arm.com pass # Not needed yet. 139113481Sgiacomo.travaglini@arm.com 139213481Sgiacomo.travaglini@arm.com def handle_typename(self): 139313481Sgiacomo.travaglini@arm.com pass # Not needed yet. 139413481Sgiacomo.travaglini@arm.com 139513481Sgiacomo.travaglini@arm.com def _GetTemplatedTypes(self): 139613481Sgiacomo.travaglini@arm.com result = {} 139713481Sgiacomo.travaglini@arm.com tokens = list(self._GetMatchingChar('<', '>')) 139813481Sgiacomo.travaglini@arm.com len_tokens = len(tokens) - 1 # Ignore trailing '>'. 139913481Sgiacomo.travaglini@arm.com i = 0 140013481Sgiacomo.travaglini@arm.com while i < len_tokens: 140113481Sgiacomo.travaglini@arm.com key = tokens[i].name 140213481Sgiacomo.travaglini@arm.com i += 1 140313481Sgiacomo.travaglini@arm.com if keywords.IsKeyword(key) or key == ',': 140413481Sgiacomo.travaglini@arm.com continue 140513481Sgiacomo.travaglini@arm.com type_name = default = None 140613481Sgiacomo.travaglini@arm.com if i < len_tokens: 140713481Sgiacomo.travaglini@arm.com i += 1 140813481Sgiacomo.travaglini@arm.com if tokens[i-1].name == '=': 140913481Sgiacomo.travaglini@arm.com assert i < len_tokens, '%s %s' % (i, tokens) 141013481Sgiacomo.travaglini@arm.com default, unused_next_token = self.GetName(tokens[i:]) 141113481Sgiacomo.travaglini@arm.com i += len(default) 141213481Sgiacomo.travaglini@arm.com else: 141313481Sgiacomo.travaglini@arm.com if tokens[i-1].name != ',': 141413481Sgiacomo.travaglini@arm.com # We got something like: Type variable. 141513481Sgiacomo.travaglini@arm.com # Re-adjust the key (variable) and type_name (Type). 141613481Sgiacomo.travaglini@arm.com key = tokens[i-1].name 141713481Sgiacomo.travaglini@arm.com type_name = tokens[i-2] 141813481Sgiacomo.travaglini@arm.com 141913481Sgiacomo.travaglini@arm.com result[key] = (type_name, default) 142013481Sgiacomo.travaglini@arm.com return result 142113481Sgiacomo.travaglini@arm.com 142213481Sgiacomo.travaglini@arm.com def handle_template(self): 142313481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 142413481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 142513481Sgiacomo.travaglini@arm.com assert token.name == '<', token 142613481Sgiacomo.travaglini@arm.com templated_types = self._GetTemplatedTypes() 142713481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): for now, just ignore the template params. 142813481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 142913481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.NAME: 143013481Sgiacomo.travaglini@arm.com if token.name == 'class': 143113481Sgiacomo.travaglini@arm.com return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types) 143213481Sgiacomo.travaglini@arm.com elif token.name == 'struct': 143313481Sgiacomo.travaglini@arm.com return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types) 143413481Sgiacomo.travaglini@arm.com elif token.name == 'friend': 143513481Sgiacomo.travaglini@arm.com return self.handle_friend() 143613481Sgiacomo.travaglini@arm.com self._AddBackToken(token) 143713481Sgiacomo.travaglini@arm.com tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';') 143813481Sgiacomo.travaglini@arm.com tokens.append(last) 143913481Sgiacomo.travaglini@arm.com self._AddBackTokens(tokens) 144013481Sgiacomo.travaglini@arm.com if last.name == '(': 144113481Sgiacomo.travaglini@arm.com return self.GetMethod(FUNCTION_NONE, templated_types) 144213481Sgiacomo.travaglini@arm.com # Must be a variable definition. 144313481Sgiacomo.travaglini@arm.com return None 144413481Sgiacomo.travaglini@arm.com 144513481Sgiacomo.travaglini@arm.com def handle_true(self): 144613481Sgiacomo.travaglini@arm.com pass # Nothing to do. 144713481Sgiacomo.travaglini@arm.com 144813481Sgiacomo.travaglini@arm.com def handle_false(self): 144913481Sgiacomo.travaglini@arm.com pass # Nothing to do. 145013481Sgiacomo.travaglini@arm.com 145113481Sgiacomo.travaglini@arm.com def handle_asm(self): 145213481Sgiacomo.travaglini@arm.com pass # Not needed yet. 145313481Sgiacomo.travaglini@arm.com 145413481Sgiacomo.travaglini@arm.com def handle_class(self): 145513481Sgiacomo.travaglini@arm.com return self._GetClass(Class, VISIBILITY_PRIVATE, None) 145613481Sgiacomo.travaglini@arm.com 145713481Sgiacomo.travaglini@arm.com def _GetBases(self): 145813481Sgiacomo.travaglini@arm.com # Get base classes. 145913481Sgiacomo.travaglini@arm.com bases = [] 146013481Sgiacomo.travaglini@arm.com while 1: 146113481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 146213481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.NAME, token 146313481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): store kind of inheritance...maybe. 146413481Sgiacomo.travaglini@arm.com if token.name not in ('public', 'protected', 'private'): 146513481Sgiacomo.travaglini@arm.com # If inheritance type is not specified, it is private. 146613481Sgiacomo.travaglini@arm.com # Just put the token back so we can form a name. 146713481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): it would be good to warn about this. 146813481Sgiacomo.travaglini@arm.com self._AddBackToken(token) 146913481Sgiacomo.travaglini@arm.com else: 147013481Sgiacomo.travaglini@arm.com # Check for virtual inheritance. 147113481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 147213481Sgiacomo.travaglini@arm.com if token.name != 'virtual': 147313481Sgiacomo.travaglini@arm.com self._AddBackToken(token) 147413481Sgiacomo.travaglini@arm.com else: 147513481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): store that we got virtual for this base. 147613481Sgiacomo.travaglini@arm.com pass 147713481Sgiacomo.travaglini@arm.com base, next_token = self.GetName() 147813481Sgiacomo.travaglini@arm.com bases_ast = self.converter.ToType(base) 147913481Sgiacomo.travaglini@arm.com assert len(bases_ast) == 1, bases_ast 148013481Sgiacomo.travaglini@arm.com bases.append(bases_ast[0]) 148113481Sgiacomo.travaglini@arm.com assert next_token.token_type == tokenize.SYNTAX, next_token 148213481Sgiacomo.travaglini@arm.com if next_token.name == '{': 148313481Sgiacomo.travaglini@arm.com token = next_token 148413481Sgiacomo.travaglini@arm.com break 148513481Sgiacomo.travaglini@arm.com # Support multiple inheritance. 148613481Sgiacomo.travaglini@arm.com assert next_token.name == ',', next_token 148713481Sgiacomo.travaglini@arm.com return bases, token 148813481Sgiacomo.travaglini@arm.com 148913481Sgiacomo.travaglini@arm.com def _GetClass(self, class_type, visibility, templated_types): 149013481Sgiacomo.travaglini@arm.com class_name = None 149113481Sgiacomo.travaglini@arm.com class_token = self._GetNextToken() 149213481Sgiacomo.travaglini@arm.com if class_token.token_type != tokenize.NAME: 149313481Sgiacomo.travaglini@arm.com assert class_token.token_type == tokenize.SYNTAX, class_token 149413481Sgiacomo.travaglini@arm.com token = class_token 149513481Sgiacomo.travaglini@arm.com else: 149613481Sgiacomo.travaglini@arm.com # Skip any macro (e.g. storage class specifiers) after the 149713481Sgiacomo.travaglini@arm.com # 'class' keyword. 149813481Sgiacomo.travaglini@arm.com next_token = self._GetNextToken() 149913481Sgiacomo.travaglini@arm.com if next_token.token_type == tokenize.NAME: 150013481Sgiacomo.travaglini@arm.com self._AddBackToken(next_token) 150113481Sgiacomo.travaglini@arm.com else: 150213481Sgiacomo.travaglini@arm.com self._AddBackTokens([class_token, next_token]) 150313481Sgiacomo.travaglini@arm.com name_tokens, token = self.GetName() 150413481Sgiacomo.travaglini@arm.com class_name = ''.join([t.name for t in name_tokens]) 150513481Sgiacomo.travaglini@arm.com bases = None 150613481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.SYNTAX: 150713481Sgiacomo.travaglini@arm.com if token.name == ';': 150813481Sgiacomo.travaglini@arm.com # Forward declaration. 150913481Sgiacomo.travaglini@arm.com return class_type(class_token.start, class_token.end, 151013481Sgiacomo.travaglini@arm.com class_name, None, templated_types, None, 151113481Sgiacomo.travaglini@arm.com self.namespace_stack) 151213481Sgiacomo.travaglini@arm.com if token.name in '*&': 151313481Sgiacomo.travaglini@arm.com # Inline forward declaration. Could be method or data. 151413481Sgiacomo.travaglini@arm.com name_token = self._GetNextToken() 151513481Sgiacomo.travaglini@arm.com next_token = self._GetNextToken() 151613481Sgiacomo.travaglini@arm.com if next_token.name == ';': 151713481Sgiacomo.travaglini@arm.com # Handle data 151813481Sgiacomo.travaglini@arm.com modifiers = ['class'] 151913481Sgiacomo.travaglini@arm.com return self._CreateVariable(class_token, name_token.name, 152013481Sgiacomo.travaglini@arm.com class_name, 152113481Sgiacomo.travaglini@arm.com modifiers, token.name, None) 152213481Sgiacomo.travaglini@arm.com else: 152313481Sgiacomo.travaglini@arm.com # Assume this is a method. 152413481Sgiacomo.travaglini@arm.com tokens = (class_token, token, name_token, next_token) 152513481Sgiacomo.travaglini@arm.com self._AddBackTokens(tokens) 152613481Sgiacomo.travaglini@arm.com return self.GetMethod(FUNCTION_NONE, None) 152713481Sgiacomo.travaglini@arm.com if token.name == ':': 152813481Sgiacomo.travaglini@arm.com bases, token = self._GetBases() 152913481Sgiacomo.travaglini@arm.com 153013481Sgiacomo.travaglini@arm.com body = None 153113481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.SYNTAX and token.name == '{': 153213481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 153313481Sgiacomo.travaglini@arm.com assert token.name == '{', token 153413481Sgiacomo.travaglini@arm.com 153513481Sgiacomo.travaglini@arm.com ast = AstBuilder(self.GetScope(), self.filename, class_name, 153613481Sgiacomo.travaglini@arm.com visibility, self.namespace_stack) 153713481Sgiacomo.travaglini@arm.com body = list(ast.Generate()) 153813481Sgiacomo.travaglini@arm.com 153913481Sgiacomo.travaglini@arm.com if not self._handling_typedef: 154013481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 154113481Sgiacomo.travaglini@arm.com if token.token_type != tokenize.NAME: 154213481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 154313481Sgiacomo.travaglini@arm.com assert token.name == ';', token 154413481Sgiacomo.travaglini@arm.com else: 154513481Sgiacomo.travaglini@arm.com new_class = class_type(class_token.start, class_token.end, 154613481Sgiacomo.travaglini@arm.com class_name, bases, None, 154713481Sgiacomo.travaglini@arm.com body, self.namespace_stack) 154813481Sgiacomo.travaglini@arm.com 154913481Sgiacomo.travaglini@arm.com modifiers = [] 155013481Sgiacomo.travaglini@arm.com return self._CreateVariable(class_token, 155113481Sgiacomo.travaglini@arm.com token.name, new_class, 155213481Sgiacomo.travaglini@arm.com modifiers, token.name, None) 155313481Sgiacomo.travaglini@arm.com else: 155413481Sgiacomo.travaglini@arm.com if not self._handling_typedef: 155513481Sgiacomo.travaglini@arm.com self.HandleError('non-typedef token', token) 155613481Sgiacomo.travaglini@arm.com self._AddBackToken(token) 155713481Sgiacomo.travaglini@arm.com 155813481Sgiacomo.travaglini@arm.com return class_type(class_token.start, class_token.end, class_name, 155913481Sgiacomo.travaglini@arm.com bases, templated_types, body, self.namespace_stack) 156013481Sgiacomo.travaglini@arm.com 156113481Sgiacomo.travaglini@arm.com def handle_namespace(self): 156213481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 156313481Sgiacomo.travaglini@arm.com # Support anonymous namespaces. 156413481Sgiacomo.travaglini@arm.com name = None 156513481Sgiacomo.travaglini@arm.com if token.token_type == tokenize.NAME: 156613481Sgiacomo.travaglini@arm.com name = token.name 156713481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 156813481Sgiacomo.travaglini@arm.com self.namespace_stack.append(name) 156913481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX, token 157013481Sgiacomo.travaglini@arm.com # Create an internal token that denotes when the namespace is complete. 157113481Sgiacomo.travaglini@arm.com internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP, 157213481Sgiacomo.travaglini@arm.com None, None) 157313481Sgiacomo.travaglini@arm.com internal_token.whence = token.whence 157413481Sgiacomo.travaglini@arm.com if token.name == '=': 157513481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): handle aliasing namespaces. 157613481Sgiacomo.travaglini@arm.com name, next_token = self.GetName() 157713481Sgiacomo.travaglini@arm.com assert next_token.name == ';', next_token 157813481Sgiacomo.travaglini@arm.com self._AddBackToken(internal_token) 157913481Sgiacomo.travaglini@arm.com else: 158013481Sgiacomo.travaglini@arm.com assert token.name == '{', token 158113481Sgiacomo.travaglini@arm.com tokens = list(self.GetScope()) 158213481Sgiacomo.travaglini@arm.com # Replace the trailing } with the internal namespace pop token. 158313481Sgiacomo.travaglini@arm.com tokens[-1] = internal_token 158413481Sgiacomo.travaglini@arm.com # Handle namespace with nothing in it. 158513481Sgiacomo.travaglini@arm.com self._AddBackTokens(tokens) 158613481Sgiacomo.travaglini@arm.com return None 158713481Sgiacomo.travaglini@arm.com 158813481Sgiacomo.travaglini@arm.com def handle_using(self): 158913481Sgiacomo.travaglini@arm.com tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 159013481Sgiacomo.travaglini@arm.com assert tokens 159113481Sgiacomo.travaglini@arm.com return Using(tokens[0].start, tokens[0].end, tokens) 159213481Sgiacomo.travaglini@arm.com 159313481Sgiacomo.travaglini@arm.com def handle_explicit(self): 159413481Sgiacomo.travaglini@arm.com assert self.in_class 159513481Sgiacomo.travaglini@arm.com # Nothing much to do. 159613481Sgiacomo.travaglini@arm.com # TODO(nnorwitz): maybe verify the method name == class name. 159713481Sgiacomo.travaglini@arm.com # This must be a ctor. 159813481Sgiacomo.travaglini@arm.com return self.GetMethod(FUNCTION_CTOR, None) 159913481Sgiacomo.travaglini@arm.com 160013481Sgiacomo.travaglini@arm.com def handle_this(self): 160113481Sgiacomo.travaglini@arm.com pass # Nothing to do. 160213481Sgiacomo.travaglini@arm.com 160313481Sgiacomo.travaglini@arm.com def handle_operator(self): 160413481Sgiacomo.travaglini@arm.com # Pull off the next token(s?) and make that part of the method name. 160513481Sgiacomo.travaglini@arm.com pass 160613481Sgiacomo.travaglini@arm.com 160713481Sgiacomo.travaglini@arm.com def handle_sizeof(self): 160813481Sgiacomo.travaglini@arm.com pass 160913481Sgiacomo.travaglini@arm.com 161013481Sgiacomo.travaglini@arm.com def handle_case(self): 161113481Sgiacomo.travaglini@arm.com pass 161213481Sgiacomo.travaglini@arm.com 161313481Sgiacomo.travaglini@arm.com def handle_switch(self): 161413481Sgiacomo.travaglini@arm.com pass 161513481Sgiacomo.travaglini@arm.com 161613481Sgiacomo.travaglini@arm.com def handle_default(self): 161713481Sgiacomo.travaglini@arm.com token = self._GetNextToken() 161813481Sgiacomo.travaglini@arm.com assert token.token_type == tokenize.SYNTAX 161913481Sgiacomo.travaglini@arm.com assert token.name == ':' 162013481Sgiacomo.travaglini@arm.com 162113481Sgiacomo.travaglini@arm.com def handle_if(self): 162213481Sgiacomo.travaglini@arm.com pass 162313481Sgiacomo.travaglini@arm.com 162413481Sgiacomo.travaglini@arm.com def handle_else(self): 162513481Sgiacomo.travaglini@arm.com pass 162613481Sgiacomo.travaglini@arm.com 162713481Sgiacomo.travaglini@arm.com def handle_return(self): 162813481Sgiacomo.travaglini@arm.com tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 162913481Sgiacomo.travaglini@arm.com if not tokens: 163013481Sgiacomo.travaglini@arm.com return Return(self.current_token.start, self.current_token.end, None) 163113481Sgiacomo.travaglini@arm.com return Return(tokens[0].start, tokens[0].end, tokens) 163213481Sgiacomo.travaglini@arm.com 163313481Sgiacomo.travaglini@arm.com def handle_goto(self): 163413481Sgiacomo.travaglini@arm.com tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 163513481Sgiacomo.travaglini@arm.com assert len(tokens) == 1, str(tokens) 163613481Sgiacomo.travaglini@arm.com return Goto(tokens[0].start, tokens[0].end, tokens[0].name) 163713481Sgiacomo.travaglini@arm.com 163813481Sgiacomo.travaglini@arm.com def handle_try(self): 163913481Sgiacomo.travaglini@arm.com pass # Not needed yet. 164013481Sgiacomo.travaglini@arm.com 164113481Sgiacomo.travaglini@arm.com def handle_catch(self): 164213481Sgiacomo.travaglini@arm.com pass # Not needed yet. 164313481Sgiacomo.travaglini@arm.com 164413481Sgiacomo.travaglini@arm.com def handle_throw(self): 164513481Sgiacomo.travaglini@arm.com pass # Not needed yet. 164613481Sgiacomo.travaglini@arm.com 164713481Sgiacomo.travaglini@arm.com def handle_while(self): 164813481Sgiacomo.travaglini@arm.com pass 164913481Sgiacomo.travaglini@arm.com 165013481Sgiacomo.travaglini@arm.com def handle_do(self): 165113481Sgiacomo.travaglini@arm.com pass 165213481Sgiacomo.travaglini@arm.com 165313481Sgiacomo.travaglini@arm.com def handle_for(self): 165413481Sgiacomo.travaglini@arm.com pass 165513481Sgiacomo.travaglini@arm.com 165613481Sgiacomo.travaglini@arm.com def handle_break(self): 165713481Sgiacomo.travaglini@arm.com self._IgnoreUpTo(tokenize.SYNTAX, ';') 165813481Sgiacomo.travaglini@arm.com 165913481Sgiacomo.travaglini@arm.com def handle_continue(self): 166013481Sgiacomo.travaglini@arm.com self._IgnoreUpTo(tokenize.SYNTAX, ';') 166113481Sgiacomo.travaglini@arm.com 166213481Sgiacomo.travaglini@arm.com 166313481Sgiacomo.travaglini@arm.comdef BuilderFromSource(source, filename): 166413481Sgiacomo.travaglini@arm.com """Utility method that returns an AstBuilder from source code. 166513481Sgiacomo.travaglini@arm.com 166613481Sgiacomo.travaglini@arm.com Args: 166713481Sgiacomo.travaglini@arm.com source: 'C++ source code' 166813481Sgiacomo.travaglini@arm.com filename: 'file1' 166913481Sgiacomo.travaglini@arm.com 167013481Sgiacomo.travaglini@arm.com Returns: 167113481Sgiacomo.travaglini@arm.com AstBuilder 167213481Sgiacomo.travaglini@arm.com """ 167313481Sgiacomo.travaglini@arm.com return AstBuilder(tokenize.GetTokens(source), filename) 167413481Sgiacomo.travaglini@arm.com 167513481Sgiacomo.travaglini@arm.com 167613481Sgiacomo.travaglini@arm.comdef PrintIndentifiers(filename, should_print): 167713481Sgiacomo.travaglini@arm.com """Prints all identifiers for a C++ source file. 167813481Sgiacomo.travaglini@arm.com 167913481Sgiacomo.travaglini@arm.com Args: 168013481Sgiacomo.travaglini@arm.com filename: 'file1' 168113481Sgiacomo.travaglini@arm.com should_print: predicate with signature: bool Function(token) 168213481Sgiacomo.travaglini@arm.com """ 168313481Sgiacomo.travaglini@arm.com source = utils.ReadFile(filename, False) 168413481Sgiacomo.travaglini@arm.com if source is None: 168513481Sgiacomo.travaglini@arm.com sys.stderr.write('Unable to find: %s\n' % filename) 168613481Sgiacomo.travaglini@arm.com return 168713481Sgiacomo.travaglini@arm.com 168813481Sgiacomo.travaglini@arm.com #print('Processing %s' % actual_filename) 168913481Sgiacomo.travaglini@arm.com builder = BuilderFromSource(source, filename) 169013481Sgiacomo.travaglini@arm.com try: 169113481Sgiacomo.travaglini@arm.com for node in builder.Generate(): 169213481Sgiacomo.travaglini@arm.com if should_print(node): 169313481Sgiacomo.travaglini@arm.com print(node.name) 169413481Sgiacomo.travaglini@arm.com except KeyboardInterrupt: 169513481Sgiacomo.travaglini@arm.com return 169613481Sgiacomo.travaglini@arm.com except: 169713481Sgiacomo.travaglini@arm.com pass 169813481Sgiacomo.travaglini@arm.com 169913481Sgiacomo.travaglini@arm.com 170013481Sgiacomo.travaglini@arm.comdef PrintAllIndentifiers(filenames, should_print): 170113481Sgiacomo.travaglini@arm.com """Prints all identifiers for each C++ source file in filenames. 170213481Sgiacomo.travaglini@arm.com 170313481Sgiacomo.travaglini@arm.com Args: 170413481Sgiacomo.travaglini@arm.com filenames: ['file1', 'file2', ...] 170513481Sgiacomo.travaglini@arm.com should_print: predicate with signature: bool Function(token) 170613481Sgiacomo.travaglini@arm.com """ 170713481Sgiacomo.travaglini@arm.com for path in filenames: 170813481Sgiacomo.travaglini@arm.com PrintIndentifiers(path, should_print) 170913481Sgiacomo.travaglini@arm.com 171013481Sgiacomo.travaglini@arm.com 171113481Sgiacomo.travaglini@arm.comdef main(argv): 171213481Sgiacomo.travaglini@arm.com for filename in argv[1:]: 171313481Sgiacomo.travaglini@arm.com source = utils.ReadFile(filename) 171413481Sgiacomo.travaglini@arm.com if source is None: 171513481Sgiacomo.travaglini@arm.com continue 171613481Sgiacomo.travaglini@arm.com 171713481Sgiacomo.travaglini@arm.com print('Processing %s' % filename) 171813481Sgiacomo.travaglini@arm.com builder = BuilderFromSource(source, filename) 171913481Sgiacomo.travaglini@arm.com try: 172013481Sgiacomo.travaglini@arm.com entire_ast = filter(None, builder.Generate()) 172113481Sgiacomo.travaglini@arm.com except KeyboardInterrupt: 172213481Sgiacomo.travaglini@arm.com return 172313481Sgiacomo.travaglini@arm.com except: 172413481Sgiacomo.travaglini@arm.com # Already printed a warning, print the traceback and continue. 172513481Sgiacomo.travaglini@arm.com traceback.print_exc() 172613481Sgiacomo.travaglini@arm.com else: 172713481Sgiacomo.travaglini@arm.com if utils.DEBUG: 172813481Sgiacomo.travaglini@arm.com for ast in entire_ast: 172913481Sgiacomo.travaglini@arm.com print(ast) 173013481Sgiacomo.travaglini@arm.com 173113481Sgiacomo.travaglini@arm.com 173213481Sgiacomo.travaglini@arm.comif __name__ == '__main__': 173313481Sgiacomo.travaglini@arm.com main(sys.argv) 1734