1f92157deSopenharmony_ci#!/usr/bin/env python 2f92157deSopenharmony_ci# 3f92157deSopenharmony_ci# Copyright 2007 Neal Norwitz 4f92157deSopenharmony_ci# Portions Copyright 2007 Google Inc. 5f92157deSopenharmony_ci# 6f92157deSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 7f92157deSopenharmony_ci# you may not use this file except in compliance with the License. 8f92157deSopenharmony_ci# You may obtain a copy of the License at 9f92157deSopenharmony_ci# 10f92157deSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 11f92157deSopenharmony_ci# 12f92157deSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 13f92157deSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 14f92157deSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15f92157deSopenharmony_ci# See the License for the specific language governing permissions and 16f92157deSopenharmony_ci# limitations under the License. 17f92157deSopenharmony_ci 18f92157deSopenharmony_ci"""Generate an Abstract Syntax Tree (AST) for C++.""" 19f92157deSopenharmony_ci 20f92157deSopenharmony_ci# FIXME: 21f92157deSopenharmony_ci# * Tokens should never be exported, need to convert to Nodes 22f92157deSopenharmony_ci# (return types, parameters, etc.) 23f92157deSopenharmony_ci# * Handle static class data for templatized classes 24f92157deSopenharmony_ci# * Handle casts (both C++ and C-style) 25f92157deSopenharmony_ci# * Handle conditions and loops (if/else, switch, for, while/do) 26f92157deSopenharmony_ci# 27f92157deSopenharmony_ci# TODO much, much later: 28f92157deSopenharmony_ci# * Handle #define 29f92157deSopenharmony_ci# * exceptions 30f92157deSopenharmony_ci 31f92157deSopenharmony_ci 32f92157deSopenharmony_citry: 33f92157deSopenharmony_ci # Python 3.x 34f92157deSopenharmony_ci import builtins 35f92157deSopenharmony_ciexcept ImportError: 36f92157deSopenharmony_ci # Python 2.x 37f92157deSopenharmony_ci import __builtin__ as builtins 38f92157deSopenharmony_ci 39f92157deSopenharmony_ciimport collections 40f92157deSopenharmony_ciimport sys 41f92157deSopenharmony_ciimport traceback 42f92157deSopenharmony_ci 43f92157deSopenharmony_cifrom cpp import keywords 44f92157deSopenharmony_cifrom cpp import tokenize 45f92157deSopenharmony_cifrom cpp import utils 46f92157deSopenharmony_ci 47f92157deSopenharmony_ci 48f92157deSopenharmony_ciif not hasattr(builtins, 'reversed'): 49f92157deSopenharmony_ci # Support Python 2.3 and earlier. 50f92157deSopenharmony_ci def reversed(seq): 51f92157deSopenharmony_ci for i in range(len(seq)-1, -1, -1): 52f92157deSopenharmony_ci yield seq[i] 53f92157deSopenharmony_ci 54f92157deSopenharmony_ciif not hasattr(builtins, 'next'): 55f92157deSopenharmony_ci # Support Python 2.5 and earlier. 56f92157deSopenharmony_ci def next(obj): 57f92157deSopenharmony_ci return obj.next() 58f92157deSopenharmony_ci 59f92157deSopenharmony_ci 60f92157deSopenharmony_ciVISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3) 61f92157deSopenharmony_ci 62f92157deSopenharmony_ciFUNCTION_NONE = 0x00 63f92157deSopenharmony_ciFUNCTION_CONST = 0x01 64f92157deSopenharmony_ciFUNCTION_VIRTUAL = 0x02 65f92157deSopenharmony_ciFUNCTION_PURE_VIRTUAL = 0x04 66f92157deSopenharmony_ciFUNCTION_CTOR = 0x08 67f92157deSopenharmony_ciFUNCTION_DTOR = 0x10 68f92157deSopenharmony_ciFUNCTION_ATTRIBUTE = 0x20 69f92157deSopenharmony_ciFUNCTION_UNKNOWN_ANNOTATION = 0x40 70f92157deSopenharmony_ciFUNCTION_THROW = 0x80 71f92157deSopenharmony_ciFUNCTION_OVERRIDE = 0x100 72f92157deSopenharmony_ci 73f92157deSopenharmony_ci""" 74f92157deSopenharmony_ciThese are currently unused. Should really handle these properly at some point. 75f92157deSopenharmony_ci 76f92157deSopenharmony_ciTYPE_MODIFIER_INLINE = 0x010000 77f92157deSopenharmony_ciTYPE_MODIFIER_EXTERN = 0x020000 78f92157deSopenharmony_ciTYPE_MODIFIER_STATIC = 0x040000 79f92157deSopenharmony_ciTYPE_MODIFIER_CONST = 0x080000 80f92157deSopenharmony_ciTYPE_MODIFIER_REGISTER = 0x100000 81f92157deSopenharmony_ciTYPE_MODIFIER_VOLATILE = 0x200000 82f92157deSopenharmony_ciTYPE_MODIFIER_MUTABLE = 0x400000 83f92157deSopenharmony_ci 84f92157deSopenharmony_ciTYPE_MODIFIER_MAP = { 85f92157deSopenharmony_ci 'inline': TYPE_MODIFIER_INLINE, 86f92157deSopenharmony_ci 'extern': TYPE_MODIFIER_EXTERN, 87f92157deSopenharmony_ci 'static': TYPE_MODIFIER_STATIC, 88f92157deSopenharmony_ci 'const': TYPE_MODIFIER_CONST, 89f92157deSopenharmony_ci 'register': TYPE_MODIFIER_REGISTER, 90f92157deSopenharmony_ci 'volatile': TYPE_MODIFIER_VOLATILE, 91f92157deSopenharmony_ci 'mutable': TYPE_MODIFIER_MUTABLE, 92f92157deSopenharmony_ci } 93f92157deSopenharmony_ci""" 94f92157deSopenharmony_ci 95f92157deSopenharmony_ci_INTERNAL_TOKEN = 'internal' 96f92157deSopenharmony_ci_NAMESPACE_POP = 'ns-pop' 97f92157deSopenharmony_ci 98f92157deSopenharmony_ci 99f92157deSopenharmony_ci# TODO(nnorwitz): use this as a singleton for templated_types, etc 100f92157deSopenharmony_ci# where we don't want to create a new empty dict each time. It is also const. 101f92157deSopenharmony_ciclass _NullDict(object): 102f92157deSopenharmony_ci __contains__ = lambda self: False 103f92157deSopenharmony_ci keys = values = items = iterkeys = itervalues = iteritems = lambda self: () 104f92157deSopenharmony_ci 105f92157deSopenharmony_ci 106f92157deSopenharmony_ci# TODO(nnorwitz): move AST nodes into a separate module. 107f92157deSopenharmony_ciclass Node(object): 108f92157deSopenharmony_ci """Base AST node.""" 109f92157deSopenharmony_ci 110f92157deSopenharmony_ci def __init__(self, start, end): 111f92157deSopenharmony_ci self.start = start 112f92157deSopenharmony_ci self.end = end 113f92157deSopenharmony_ci 114f92157deSopenharmony_ci def IsDeclaration(self): 115f92157deSopenharmony_ci """Returns bool if this node is a declaration.""" 116f92157deSopenharmony_ci return False 117f92157deSopenharmony_ci 118f92157deSopenharmony_ci def IsDefinition(self): 119f92157deSopenharmony_ci """Returns bool if this node is a definition.""" 120f92157deSopenharmony_ci return False 121f92157deSopenharmony_ci 122f92157deSopenharmony_ci def IsExportable(self): 123f92157deSopenharmony_ci """Returns bool if this node exportable from a header file.""" 124f92157deSopenharmony_ci return False 125f92157deSopenharmony_ci 126f92157deSopenharmony_ci def Requires(self, node): 127f92157deSopenharmony_ci """Does this AST node require the definition of the node passed in?""" 128f92157deSopenharmony_ci return False 129f92157deSopenharmony_ci 130f92157deSopenharmony_ci def XXX__str__(self): 131f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, '') 132f92157deSopenharmony_ci 133f92157deSopenharmony_ci def _StringHelper(self, name, suffix): 134f92157deSopenharmony_ci if not utils.DEBUG: 135f92157deSopenharmony_ci return '%s(%s)' % (name, suffix) 136f92157deSopenharmony_ci return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix) 137f92157deSopenharmony_ci 138f92157deSopenharmony_ci def __repr__(self): 139f92157deSopenharmony_ci return str(self) 140f92157deSopenharmony_ci 141f92157deSopenharmony_ci 142f92157deSopenharmony_ciclass Define(Node): 143f92157deSopenharmony_ci def __init__(self, start, end, name, definition): 144f92157deSopenharmony_ci Node.__init__(self, start, end) 145f92157deSopenharmony_ci self.name = name 146f92157deSopenharmony_ci self.definition = definition 147f92157deSopenharmony_ci 148f92157deSopenharmony_ci def __str__(self): 149f92157deSopenharmony_ci value = '%s %s' % (self.name, self.definition) 150f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, value) 151f92157deSopenharmony_ci 152f92157deSopenharmony_ci 153f92157deSopenharmony_ciclass Include(Node): 154f92157deSopenharmony_ci def __init__(self, start, end, filename, system): 155f92157deSopenharmony_ci Node.__init__(self, start, end) 156f92157deSopenharmony_ci self.filename = filename 157f92157deSopenharmony_ci self.system = system 158f92157deSopenharmony_ci 159f92157deSopenharmony_ci def __str__(self): 160f92157deSopenharmony_ci fmt = '"%s"' 161f92157deSopenharmony_ci if self.system: 162f92157deSopenharmony_ci fmt = '<%s>' 163f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, fmt % self.filename) 164f92157deSopenharmony_ci 165f92157deSopenharmony_ci 166f92157deSopenharmony_ciclass Goto(Node): 167f92157deSopenharmony_ci def __init__(self, start, end, label): 168f92157deSopenharmony_ci Node.__init__(self, start, end) 169f92157deSopenharmony_ci self.label = label 170f92157deSopenharmony_ci 171f92157deSopenharmony_ci def __str__(self): 172f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, str(self.label)) 173f92157deSopenharmony_ci 174f92157deSopenharmony_ci 175f92157deSopenharmony_ciclass Expr(Node): 176f92157deSopenharmony_ci def __init__(self, start, end, expr): 177f92157deSopenharmony_ci Node.__init__(self, start, end) 178f92157deSopenharmony_ci self.expr = expr 179f92157deSopenharmony_ci 180f92157deSopenharmony_ci def Requires(self, node): 181f92157deSopenharmony_ci # TODO(nnorwitz): impl. 182f92157deSopenharmony_ci return False 183f92157deSopenharmony_ci 184f92157deSopenharmony_ci def __str__(self): 185f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, str(self.expr)) 186f92157deSopenharmony_ci 187f92157deSopenharmony_ci 188f92157deSopenharmony_ciclass Return(Expr): 189f92157deSopenharmony_ci pass 190f92157deSopenharmony_ci 191f92157deSopenharmony_ci 192f92157deSopenharmony_ciclass Delete(Expr): 193f92157deSopenharmony_ci pass 194f92157deSopenharmony_ci 195f92157deSopenharmony_ci 196f92157deSopenharmony_ciclass Friend(Expr): 197f92157deSopenharmony_ci def __init__(self, start, end, expr, namespace): 198f92157deSopenharmony_ci Expr.__init__(self, start, end, expr) 199f92157deSopenharmony_ci self.namespace = namespace[:] 200f92157deSopenharmony_ci 201f92157deSopenharmony_ci 202f92157deSopenharmony_ciclass Using(Node): 203f92157deSopenharmony_ci def __init__(self, start, end, names): 204f92157deSopenharmony_ci Node.__init__(self, start, end) 205f92157deSopenharmony_ci self.names = names 206f92157deSopenharmony_ci 207f92157deSopenharmony_ci def __str__(self): 208f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, str(self.names)) 209f92157deSopenharmony_ci 210f92157deSopenharmony_ci 211f92157deSopenharmony_ciclass Parameter(Node): 212f92157deSopenharmony_ci def __init__(self, start, end, name, parameter_type, default): 213f92157deSopenharmony_ci Node.__init__(self, start, end) 214f92157deSopenharmony_ci self.name = name 215f92157deSopenharmony_ci self.type = parameter_type 216f92157deSopenharmony_ci self.default = default 217f92157deSopenharmony_ci 218f92157deSopenharmony_ci def Requires(self, node): 219f92157deSopenharmony_ci # TODO(nnorwitz): handle namespaces, etc. 220f92157deSopenharmony_ci return self.type.name == node.name 221f92157deSopenharmony_ci 222f92157deSopenharmony_ci def __str__(self): 223f92157deSopenharmony_ci name = str(self.type) 224f92157deSopenharmony_ci suffix = '%s %s' % (name, self.name) 225f92157deSopenharmony_ci if self.default: 226f92157deSopenharmony_ci suffix += ' = ' + ''.join([d.name for d in self.default]) 227f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, suffix) 228f92157deSopenharmony_ci 229f92157deSopenharmony_ci 230f92157deSopenharmony_ciclass _GenericDeclaration(Node): 231f92157deSopenharmony_ci def __init__(self, start, end, name, namespace): 232f92157deSopenharmony_ci Node.__init__(self, start, end) 233f92157deSopenharmony_ci self.name = name 234f92157deSopenharmony_ci self.namespace = namespace[:] 235f92157deSopenharmony_ci 236f92157deSopenharmony_ci def FullName(self): 237f92157deSopenharmony_ci prefix = '' 238f92157deSopenharmony_ci if self.namespace and self.namespace[-1]: 239f92157deSopenharmony_ci prefix = '::'.join(self.namespace) + '::' 240f92157deSopenharmony_ci return prefix + self.name 241f92157deSopenharmony_ci 242f92157deSopenharmony_ci def _TypeStringHelper(self, suffix): 243f92157deSopenharmony_ci if self.namespace: 244f92157deSopenharmony_ci names = [n or '<anonymous>' for n in self.namespace] 245f92157deSopenharmony_ci suffix += ' in ' + '::'.join(names) 246f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, suffix) 247f92157deSopenharmony_ci 248f92157deSopenharmony_ci 249f92157deSopenharmony_ci# TODO(nnorwitz): merge with Parameter in some way? 250f92157deSopenharmony_ciclass VariableDeclaration(_GenericDeclaration): 251f92157deSopenharmony_ci def __init__(self, start, end, name, var_type, initial_value, namespace): 252f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, namespace) 253f92157deSopenharmony_ci self.type = var_type 254f92157deSopenharmony_ci self.initial_value = initial_value 255f92157deSopenharmony_ci 256f92157deSopenharmony_ci def Requires(self, node): 257f92157deSopenharmony_ci # TODO(nnorwitz): handle namespaces, etc. 258f92157deSopenharmony_ci return self.type.name == node.name 259f92157deSopenharmony_ci 260f92157deSopenharmony_ci def ToString(self): 261f92157deSopenharmony_ci """Return a string that tries to reconstitute the variable decl.""" 262f92157deSopenharmony_ci suffix = '%s %s' % (self.type, self.name) 263f92157deSopenharmony_ci if self.initial_value: 264f92157deSopenharmony_ci suffix += ' = ' + self.initial_value 265f92157deSopenharmony_ci return suffix 266f92157deSopenharmony_ci 267f92157deSopenharmony_ci def __str__(self): 268f92157deSopenharmony_ci return self._StringHelper(self.__class__.__name__, self.ToString()) 269f92157deSopenharmony_ci 270f92157deSopenharmony_ci 271f92157deSopenharmony_ciclass Typedef(_GenericDeclaration): 272f92157deSopenharmony_ci def __init__(self, start, end, name, alias, namespace): 273f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, namespace) 274f92157deSopenharmony_ci self.alias = alias 275f92157deSopenharmony_ci 276f92157deSopenharmony_ci def IsDefinition(self): 277f92157deSopenharmony_ci return True 278f92157deSopenharmony_ci 279f92157deSopenharmony_ci def IsExportable(self): 280f92157deSopenharmony_ci return True 281f92157deSopenharmony_ci 282f92157deSopenharmony_ci def Requires(self, node): 283f92157deSopenharmony_ci # TODO(nnorwitz): handle namespaces, etc. 284f92157deSopenharmony_ci name = node.name 285f92157deSopenharmony_ci for token in self.alias: 286f92157deSopenharmony_ci if token is not None and name == token.name: 287f92157deSopenharmony_ci return True 288f92157deSopenharmony_ci return False 289f92157deSopenharmony_ci 290f92157deSopenharmony_ci def __str__(self): 291f92157deSopenharmony_ci suffix = '%s, %s' % (self.name, self.alias) 292f92157deSopenharmony_ci return self._TypeStringHelper(suffix) 293f92157deSopenharmony_ci 294f92157deSopenharmony_ci 295f92157deSopenharmony_ciclass _NestedType(_GenericDeclaration): 296f92157deSopenharmony_ci def __init__(self, start, end, name, fields, namespace): 297f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, namespace) 298f92157deSopenharmony_ci self.fields = fields 299f92157deSopenharmony_ci 300f92157deSopenharmony_ci def IsDefinition(self): 301f92157deSopenharmony_ci return True 302f92157deSopenharmony_ci 303f92157deSopenharmony_ci def IsExportable(self): 304f92157deSopenharmony_ci return True 305f92157deSopenharmony_ci 306f92157deSopenharmony_ci def __str__(self): 307f92157deSopenharmony_ci suffix = '%s, {%s}' % (self.name, self.fields) 308f92157deSopenharmony_ci return self._TypeStringHelper(suffix) 309f92157deSopenharmony_ci 310f92157deSopenharmony_ci 311f92157deSopenharmony_ciclass Union(_NestedType): 312f92157deSopenharmony_ci pass 313f92157deSopenharmony_ci 314f92157deSopenharmony_ci 315f92157deSopenharmony_ciclass Enum(_NestedType): 316f92157deSopenharmony_ci pass 317f92157deSopenharmony_ci 318f92157deSopenharmony_ci 319f92157deSopenharmony_ciclass Class(_GenericDeclaration): 320f92157deSopenharmony_ci def __init__(self, start, end, name, bases, templated_types, body, namespace): 321f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, namespace) 322f92157deSopenharmony_ci self.bases = bases 323f92157deSopenharmony_ci self.body = body 324f92157deSopenharmony_ci self.templated_types = templated_types 325f92157deSopenharmony_ci 326f92157deSopenharmony_ci def IsDeclaration(self): 327f92157deSopenharmony_ci return self.bases is None and self.body is None 328f92157deSopenharmony_ci 329f92157deSopenharmony_ci def IsDefinition(self): 330f92157deSopenharmony_ci return not self.IsDeclaration() 331f92157deSopenharmony_ci 332f92157deSopenharmony_ci def IsExportable(self): 333f92157deSopenharmony_ci return not self.IsDeclaration() 334f92157deSopenharmony_ci 335f92157deSopenharmony_ci def Requires(self, node): 336f92157deSopenharmony_ci # TODO(nnorwitz): handle namespaces, etc. 337f92157deSopenharmony_ci if self.bases: 338f92157deSopenharmony_ci for token_list in self.bases: 339f92157deSopenharmony_ci # TODO(nnorwitz): bases are tokens, do name comparison. 340f92157deSopenharmony_ci for token in token_list: 341f92157deSopenharmony_ci if token.name == node.name: 342f92157deSopenharmony_ci return True 343f92157deSopenharmony_ci # TODO(nnorwitz): search in body too. 344f92157deSopenharmony_ci return False 345f92157deSopenharmony_ci 346f92157deSopenharmony_ci def __str__(self): 347f92157deSopenharmony_ci name = self.name 348f92157deSopenharmony_ci if self.templated_types: 349f92157deSopenharmony_ci name += '<%s>' % self.templated_types 350f92157deSopenharmony_ci suffix = '%s, %s, %s' % (name, self.bases, self.body) 351f92157deSopenharmony_ci return self._TypeStringHelper(suffix) 352f92157deSopenharmony_ci 353f92157deSopenharmony_ci 354f92157deSopenharmony_ciclass Struct(Class): 355f92157deSopenharmony_ci pass 356f92157deSopenharmony_ci 357f92157deSopenharmony_ci 358f92157deSopenharmony_ciclass Function(_GenericDeclaration): 359f92157deSopenharmony_ci def __init__(self, start, end, name, return_type, parameters, 360f92157deSopenharmony_ci modifiers, templated_types, body, namespace): 361f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, namespace) 362f92157deSopenharmony_ci converter = TypeConverter(namespace) 363f92157deSopenharmony_ci self.return_type = converter.CreateReturnType(return_type) 364f92157deSopenharmony_ci self.parameters = converter.ToParameters(parameters) 365f92157deSopenharmony_ci self.modifiers = modifiers 366f92157deSopenharmony_ci self.body = body 367f92157deSopenharmony_ci self.templated_types = templated_types 368f92157deSopenharmony_ci 369f92157deSopenharmony_ci def IsDeclaration(self): 370f92157deSopenharmony_ci return self.body is None 371f92157deSopenharmony_ci 372f92157deSopenharmony_ci def IsDefinition(self): 373f92157deSopenharmony_ci return self.body is not None 374f92157deSopenharmony_ci 375f92157deSopenharmony_ci def IsExportable(self): 376f92157deSopenharmony_ci if self.return_type and 'static' in self.return_type.modifiers: 377f92157deSopenharmony_ci return False 378f92157deSopenharmony_ci return None not in self.namespace 379f92157deSopenharmony_ci 380f92157deSopenharmony_ci def Requires(self, node): 381f92157deSopenharmony_ci if self.parameters: 382f92157deSopenharmony_ci # TODO(nnorwitz): parameters are tokens, do name comparison. 383f92157deSopenharmony_ci for p in self.parameters: 384f92157deSopenharmony_ci if p.name == node.name: 385f92157deSopenharmony_ci return True 386f92157deSopenharmony_ci # TODO(nnorwitz): search in body too. 387f92157deSopenharmony_ci return False 388f92157deSopenharmony_ci 389f92157deSopenharmony_ci def __str__(self): 390f92157deSopenharmony_ci # TODO(nnorwitz): add templated_types. 391f92157deSopenharmony_ci suffix = ('%s %s(%s), 0x%02x, %s' % 392f92157deSopenharmony_ci (self.return_type, self.name, self.parameters, 393f92157deSopenharmony_ci self.modifiers, self.body)) 394f92157deSopenharmony_ci return self._TypeStringHelper(suffix) 395f92157deSopenharmony_ci 396f92157deSopenharmony_ci 397f92157deSopenharmony_ciclass Method(Function): 398f92157deSopenharmony_ci def __init__(self, start, end, name, in_class, return_type, parameters, 399f92157deSopenharmony_ci modifiers, templated_types, body, namespace): 400f92157deSopenharmony_ci Function.__init__(self, start, end, name, return_type, parameters, 401f92157deSopenharmony_ci modifiers, templated_types, body, namespace) 402f92157deSopenharmony_ci # TODO(nnorwitz): in_class could also be a namespace which can 403f92157deSopenharmony_ci # mess up finding functions properly. 404f92157deSopenharmony_ci self.in_class = in_class 405f92157deSopenharmony_ci 406f92157deSopenharmony_ci 407f92157deSopenharmony_ciclass Type(_GenericDeclaration): 408f92157deSopenharmony_ci """Type used for any variable (eg class, primitive, struct, etc).""" 409f92157deSopenharmony_ci 410f92157deSopenharmony_ci def __init__(self, start, end, name, templated_types, modifiers, 411f92157deSopenharmony_ci reference, pointer, array): 412f92157deSopenharmony_ci """ 413f92157deSopenharmony_ci Args: 414f92157deSopenharmony_ci name: str name of main type 415f92157deSopenharmony_ci templated_types: [Class (Type?)] template type info between <> 416f92157deSopenharmony_ci modifiers: [str] type modifiers (keywords) eg, const, mutable, etc. 417f92157deSopenharmony_ci reference, pointer, array: bools 418f92157deSopenharmony_ci """ 419f92157deSopenharmony_ci _GenericDeclaration.__init__(self, start, end, name, []) 420f92157deSopenharmony_ci self.templated_types = templated_types 421f92157deSopenharmony_ci if not name and modifiers: 422f92157deSopenharmony_ci self.name = modifiers.pop() 423f92157deSopenharmony_ci self.modifiers = modifiers 424f92157deSopenharmony_ci self.reference = reference 425f92157deSopenharmony_ci self.pointer = pointer 426f92157deSopenharmony_ci self.array = array 427f92157deSopenharmony_ci 428f92157deSopenharmony_ci def __str__(self): 429f92157deSopenharmony_ci prefix = '' 430f92157deSopenharmony_ci if self.modifiers: 431f92157deSopenharmony_ci prefix = ' '.join(self.modifiers) + ' ' 432f92157deSopenharmony_ci name = str(self.name) 433f92157deSopenharmony_ci if self.templated_types: 434f92157deSopenharmony_ci name += '<%s>' % self.templated_types 435f92157deSopenharmony_ci suffix = prefix + name 436f92157deSopenharmony_ci if self.reference: 437f92157deSopenharmony_ci suffix += '&' 438f92157deSopenharmony_ci if self.pointer: 439f92157deSopenharmony_ci suffix += '*' 440f92157deSopenharmony_ci if self.array: 441f92157deSopenharmony_ci suffix += '[]' 442f92157deSopenharmony_ci return self._TypeStringHelper(suffix) 443f92157deSopenharmony_ci 444f92157deSopenharmony_ci # By definition, Is* are always False. A Type can only exist in 445f92157deSopenharmony_ci # some sort of variable declaration, parameter, or return value. 446f92157deSopenharmony_ci def IsDeclaration(self): 447f92157deSopenharmony_ci return False 448f92157deSopenharmony_ci 449f92157deSopenharmony_ci def IsDefinition(self): 450f92157deSopenharmony_ci return False 451f92157deSopenharmony_ci 452f92157deSopenharmony_ci def IsExportable(self): 453f92157deSopenharmony_ci return False 454f92157deSopenharmony_ci 455f92157deSopenharmony_ci 456f92157deSopenharmony_ciclass TypeConverter(object): 457f92157deSopenharmony_ci 458f92157deSopenharmony_ci def __init__(self, namespace_stack): 459f92157deSopenharmony_ci self.namespace_stack = namespace_stack 460f92157deSopenharmony_ci 461f92157deSopenharmony_ci def _GetTemplateEnd(self, tokens, start): 462f92157deSopenharmony_ci count = 1 463f92157deSopenharmony_ci end = start 464f92157deSopenharmony_ci while 1: 465f92157deSopenharmony_ci token = tokens[end] 466f92157deSopenharmony_ci end += 1 467f92157deSopenharmony_ci if token.name == '<': 468f92157deSopenharmony_ci count += 1 469f92157deSopenharmony_ci elif token.name == '>': 470f92157deSopenharmony_ci count -= 1 471f92157deSopenharmony_ci if count == 0: 472f92157deSopenharmony_ci break 473f92157deSopenharmony_ci return tokens[start:end-1], end 474f92157deSopenharmony_ci 475f92157deSopenharmony_ci def ToType(self, tokens): 476f92157deSopenharmony_ci """Convert [Token,...] to [Class(...), ] useful for base classes. 477f92157deSopenharmony_ci For example, code like class Foo : public Bar<x, y> { ... }; 478f92157deSopenharmony_ci the "Bar<x, y>" portion gets converted to an AST. 479f92157deSopenharmony_ci 480f92157deSopenharmony_ci Returns: 481f92157deSopenharmony_ci [Class(...), ...] 482f92157deSopenharmony_ci """ 483f92157deSopenharmony_ci result = [] 484f92157deSopenharmony_ci name_tokens = [] 485f92157deSopenharmony_ci reference = pointer = array = False 486f92157deSopenharmony_ci 487f92157deSopenharmony_ci def AddType(templated_types): 488f92157deSopenharmony_ci # Partition tokens into name and modifier tokens. 489f92157deSopenharmony_ci names = [] 490f92157deSopenharmony_ci modifiers = [] 491f92157deSopenharmony_ci for t in name_tokens: 492f92157deSopenharmony_ci if keywords.IsKeyword(t.name): 493f92157deSopenharmony_ci modifiers.append(t.name) 494f92157deSopenharmony_ci else: 495f92157deSopenharmony_ci names.append(t.name) 496f92157deSopenharmony_ci name = ''.join(names) 497f92157deSopenharmony_ci if name_tokens: 498f92157deSopenharmony_ci result.append(Type(name_tokens[0].start, name_tokens[-1].end, 499f92157deSopenharmony_ci name, templated_types, modifiers, 500f92157deSopenharmony_ci reference, pointer, array)) 501f92157deSopenharmony_ci del name_tokens[:] 502f92157deSopenharmony_ci 503f92157deSopenharmony_ci i = 0 504f92157deSopenharmony_ci end = len(tokens) 505f92157deSopenharmony_ci while i < end: 506f92157deSopenharmony_ci token = tokens[i] 507f92157deSopenharmony_ci if token.name == '<': 508f92157deSopenharmony_ci new_tokens, new_end = self._GetTemplateEnd(tokens, i+1) 509f92157deSopenharmony_ci AddType(self.ToType(new_tokens)) 510f92157deSopenharmony_ci # If there is a comma after the template, we need to consume 511f92157deSopenharmony_ci # that here otherwise it becomes part of the name. 512f92157deSopenharmony_ci i = new_end 513f92157deSopenharmony_ci reference = pointer = array = False 514f92157deSopenharmony_ci elif token.name == ',': 515f92157deSopenharmony_ci AddType([]) 516f92157deSopenharmony_ci reference = pointer = array = False 517f92157deSopenharmony_ci elif token.name == '*': 518f92157deSopenharmony_ci pointer = True 519f92157deSopenharmony_ci elif token.name == '&': 520f92157deSopenharmony_ci reference = True 521f92157deSopenharmony_ci elif token.name == '[': 522f92157deSopenharmony_ci pointer = True 523f92157deSopenharmony_ci elif token.name == ']': 524f92157deSopenharmony_ci pass 525f92157deSopenharmony_ci else: 526f92157deSopenharmony_ci name_tokens.append(token) 527f92157deSopenharmony_ci i += 1 528f92157deSopenharmony_ci 529f92157deSopenharmony_ci if name_tokens: 530f92157deSopenharmony_ci # No '<' in the tokens, just a simple name and no template. 531f92157deSopenharmony_ci AddType([]) 532f92157deSopenharmony_ci return result 533f92157deSopenharmony_ci 534f92157deSopenharmony_ci def DeclarationToParts(self, parts, needs_name_removed): 535f92157deSopenharmony_ci name = None 536f92157deSopenharmony_ci default = [] 537f92157deSopenharmony_ci if needs_name_removed: 538f92157deSopenharmony_ci # Handle default (initial) values properly. 539f92157deSopenharmony_ci for i, t in enumerate(parts): 540f92157deSopenharmony_ci if t.name == '=': 541f92157deSopenharmony_ci default = parts[i+1:] 542f92157deSopenharmony_ci name = parts[i-1].name 543f92157deSopenharmony_ci if name == ']' and parts[i-2].name == '[': 544f92157deSopenharmony_ci name = parts[i-3].name 545f92157deSopenharmony_ci i -= 1 546f92157deSopenharmony_ci parts = parts[:i-1] 547f92157deSopenharmony_ci break 548f92157deSopenharmony_ci else: 549f92157deSopenharmony_ci if parts[-1].token_type == tokenize.NAME: 550f92157deSopenharmony_ci name = parts.pop().name 551f92157deSopenharmony_ci else: 552f92157deSopenharmony_ci # TODO(nnorwitz): this is a hack that happens for code like 553f92157deSopenharmony_ci # Register(Foo<T>); where it thinks this is a function call 554f92157deSopenharmony_ci # but it's actually a declaration. 555f92157deSopenharmony_ci name = '???' 556f92157deSopenharmony_ci modifiers = [] 557f92157deSopenharmony_ci type_name = [] 558f92157deSopenharmony_ci other_tokens = [] 559f92157deSopenharmony_ci templated_types = [] 560f92157deSopenharmony_ci i = 0 561f92157deSopenharmony_ci end = len(parts) 562f92157deSopenharmony_ci while i < end: 563f92157deSopenharmony_ci p = parts[i] 564f92157deSopenharmony_ci if keywords.IsKeyword(p.name): 565f92157deSopenharmony_ci modifiers.append(p.name) 566f92157deSopenharmony_ci elif p.name == '<': 567f92157deSopenharmony_ci templated_tokens, new_end = self._GetTemplateEnd(parts, i+1) 568f92157deSopenharmony_ci templated_types = self.ToType(templated_tokens) 569f92157deSopenharmony_ci i = new_end - 1 570f92157deSopenharmony_ci # Don't add a spurious :: to data members being initialized. 571f92157deSopenharmony_ci next_index = i + 1 572f92157deSopenharmony_ci if next_index < end and parts[next_index].name == '::': 573f92157deSopenharmony_ci i += 1 574f92157deSopenharmony_ci elif p.name in ('[', ']', '='): 575f92157deSopenharmony_ci # These are handled elsewhere. 576f92157deSopenharmony_ci other_tokens.append(p) 577f92157deSopenharmony_ci elif p.name not in ('*', '&', '>'): 578f92157deSopenharmony_ci # Ensure that names have a space between them. 579f92157deSopenharmony_ci if (type_name and type_name[-1].token_type == tokenize.NAME and 580f92157deSopenharmony_ci p.token_type == tokenize.NAME): 581f92157deSopenharmony_ci type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0)) 582f92157deSopenharmony_ci type_name.append(p) 583f92157deSopenharmony_ci else: 584f92157deSopenharmony_ci other_tokens.append(p) 585f92157deSopenharmony_ci i += 1 586f92157deSopenharmony_ci type_name = ''.join([t.name for t in type_name]) 587f92157deSopenharmony_ci return name, type_name, templated_types, modifiers, default, other_tokens 588f92157deSopenharmony_ci 589f92157deSopenharmony_ci def ToParameters(self, tokens): 590f92157deSopenharmony_ci if not tokens: 591f92157deSopenharmony_ci return [] 592f92157deSopenharmony_ci 593f92157deSopenharmony_ci result = [] 594f92157deSopenharmony_ci name = type_name = '' 595f92157deSopenharmony_ci type_modifiers = [] 596f92157deSopenharmony_ci pointer = reference = array = False 597f92157deSopenharmony_ci first_token = None 598f92157deSopenharmony_ci default = [] 599f92157deSopenharmony_ci 600f92157deSopenharmony_ci def AddParameter(end): 601f92157deSopenharmony_ci if default: 602f92157deSopenharmony_ci del default[0] # Remove flag. 603f92157deSopenharmony_ci parts = self.DeclarationToParts(type_modifiers, True) 604f92157deSopenharmony_ci (name, type_name, templated_types, modifiers, 605f92157deSopenharmony_ci unused_default, unused_other_tokens) = parts 606f92157deSopenharmony_ci parameter_type = Type(first_token.start, first_token.end, 607f92157deSopenharmony_ci type_name, templated_types, modifiers, 608f92157deSopenharmony_ci reference, pointer, array) 609f92157deSopenharmony_ci p = Parameter(first_token.start, end, name, 610f92157deSopenharmony_ci parameter_type, default) 611f92157deSopenharmony_ci result.append(p) 612f92157deSopenharmony_ci 613f92157deSopenharmony_ci template_count = 0 614f92157deSopenharmony_ci brace_count = 0 615f92157deSopenharmony_ci for s in tokens: 616f92157deSopenharmony_ci if not first_token: 617f92157deSopenharmony_ci first_token = s 618f92157deSopenharmony_ci 619f92157deSopenharmony_ci # Check for braces before templates, as we can have unmatched '<>' 620f92157deSopenharmony_ci # inside default arguments. 621f92157deSopenharmony_ci if s.name == '{': 622f92157deSopenharmony_ci brace_count += 1 623f92157deSopenharmony_ci elif s.name == '}': 624f92157deSopenharmony_ci brace_count -= 1 625f92157deSopenharmony_ci if brace_count > 0: 626f92157deSopenharmony_ci type_modifiers.append(s) 627f92157deSopenharmony_ci continue 628f92157deSopenharmony_ci 629f92157deSopenharmony_ci if s.name == '<': 630f92157deSopenharmony_ci template_count += 1 631f92157deSopenharmony_ci elif s.name == '>': 632f92157deSopenharmony_ci template_count -= 1 633f92157deSopenharmony_ci if template_count > 0: 634f92157deSopenharmony_ci type_modifiers.append(s) 635f92157deSopenharmony_ci continue 636f92157deSopenharmony_ci 637f92157deSopenharmony_ci if s.name == ',': 638f92157deSopenharmony_ci AddParameter(s.start) 639f92157deSopenharmony_ci name = type_name = '' 640f92157deSopenharmony_ci type_modifiers = [] 641f92157deSopenharmony_ci pointer = reference = array = False 642f92157deSopenharmony_ci first_token = None 643f92157deSopenharmony_ci default = [] 644f92157deSopenharmony_ci elif s.name == '*': 645f92157deSopenharmony_ci pointer = True 646f92157deSopenharmony_ci elif s.name == '&': 647f92157deSopenharmony_ci reference = True 648f92157deSopenharmony_ci elif s.name == '[': 649f92157deSopenharmony_ci array = True 650f92157deSopenharmony_ci elif s.name == ']': 651f92157deSopenharmony_ci pass # Just don't add to type_modifiers. 652f92157deSopenharmony_ci elif s.name == '=': 653f92157deSopenharmony_ci # Got a default value. Add any value (None) as a flag. 654f92157deSopenharmony_ci default.append(None) 655f92157deSopenharmony_ci elif default: 656f92157deSopenharmony_ci default.append(s) 657f92157deSopenharmony_ci else: 658f92157deSopenharmony_ci type_modifiers.append(s) 659f92157deSopenharmony_ci AddParameter(tokens[-1].end) 660f92157deSopenharmony_ci return result 661f92157deSopenharmony_ci 662f92157deSopenharmony_ci def CreateReturnType(self, return_type_seq): 663f92157deSopenharmony_ci if not return_type_seq: 664f92157deSopenharmony_ci return None 665f92157deSopenharmony_ci start = return_type_seq[0].start 666f92157deSopenharmony_ci end = return_type_seq[-1].end 667f92157deSopenharmony_ci _, name, templated_types, modifiers, default, other_tokens = \ 668f92157deSopenharmony_ci self.DeclarationToParts(return_type_seq, False) 669f92157deSopenharmony_ci names = [n.name for n in other_tokens] 670f92157deSopenharmony_ci reference = '&' in names 671f92157deSopenharmony_ci pointer = '*' in names 672f92157deSopenharmony_ci array = '[' in names 673f92157deSopenharmony_ci return Type(start, end, name, templated_types, modifiers, 674f92157deSopenharmony_ci reference, pointer, array) 675f92157deSopenharmony_ci 676f92157deSopenharmony_ci def GetTemplateIndices(self, names): 677f92157deSopenharmony_ci # names is a list of strings. 678f92157deSopenharmony_ci start = names.index('<') 679f92157deSopenharmony_ci end = len(names) - 1 680f92157deSopenharmony_ci while end > 0: 681f92157deSopenharmony_ci if names[end] == '>': 682f92157deSopenharmony_ci break 683f92157deSopenharmony_ci end -= 1 684f92157deSopenharmony_ci return start, end+1 685f92157deSopenharmony_ci 686f92157deSopenharmony_ciclass AstBuilder(object): 687f92157deSopenharmony_ci def __init__(self, token_stream, filename, in_class='', visibility=None, 688f92157deSopenharmony_ci namespace_stack=[]): 689f92157deSopenharmony_ci self.tokens = token_stream 690f92157deSopenharmony_ci self.filename = filename 691f92157deSopenharmony_ci # TODO(nnorwitz): use a better data structure (deque) for the queue. 692f92157deSopenharmony_ci # Switching directions of the "queue" improved perf by about 25%. 693f92157deSopenharmony_ci # Using a deque should be even better since we access from both sides. 694f92157deSopenharmony_ci self.token_queue = [] 695f92157deSopenharmony_ci self.namespace_stack = namespace_stack[:] 696f92157deSopenharmony_ci self.in_class = in_class 697f92157deSopenharmony_ci if in_class is None: 698f92157deSopenharmony_ci self.in_class_name_only = None 699f92157deSopenharmony_ci else: 700f92157deSopenharmony_ci self.in_class_name_only = in_class.split('::')[-1] 701f92157deSopenharmony_ci self.visibility = visibility 702f92157deSopenharmony_ci self.in_function = False 703f92157deSopenharmony_ci self.current_token = None 704f92157deSopenharmony_ci # Keep the state whether we are currently handling a typedef or not. 705f92157deSopenharmony_ci self._handling_typedef = False 706f92157deSopenharmony_ci 707f92157deSopenharmony_ci self.converter = TypeConverter(self.namespace_stack) 708f92157deSopenharmony_ci 709f92157deSopenharmony_ci def HandleError(self, msg, token): 710f92157deSopenharmony_ci printable_queue = list(reversed(self.token_queue[-20:])) 711f92157deSopenharmony_ci sys.stderr.write('Got %s in %s @ %s %s\n' % 712f92157deSopenharmony_ci (msg, self.filename, token, printable_queue)) 713f92157deSopenharmony_ci 714f92157deSopenharmony_ci def Generate(self): 715f92157deSopenharmony_ci while 1: 716f92157deSopenharmony_ci token = self._GetNextToken() 717f92157deSopenharmony_ci if not token: 718f92157deSopenharmony_ci break 719f92157deSopenharmony_ci 720f92157deSopenharmony_ci # Get the next token. 721f92157deSopenharmony_ci self.current_token = token 722f92157deSopenharmony_ci 723f92157deSopenharmony_ci # Dispatch on the next token type. 724f92157deSopenharmony_ci if token.token_type == _INTERNAL_TOKEN: 725f92157deSopenharmony_ci if token.name == _NAMESPACE_POP: 726f92157deSopenharmony_ci self.namespace_stack.pop() 727f92157deSopenharmony_ci continue 728f92157deSopenharmony_ci 729f92157deSopenharmony_ci try: 730f92157deSopenharmony_ci result = self._GenerateOne(token) 731f92157deSopenharmony_ci if result is not None: 732f92157deSopenharmony_ci yield result 733f92157deSopenharmony_ci except: 734f92157deSopenharmony_ci self.HandleError('exception', token) 735f92157deSopenharmony_ci raise 736f92157deSopenharmony_ci 737f92157deSopenharmony_ci def _CreateVariable(self, pos_token, name, type_name, type_modifiers, 738f92157deSopenharmony_ci ref_pointer_name_seq, templated_types, value=None): 739f92157deSopenharmony_ci reference = '&' in ref_pointer_name_seq 740f92157deSopenharmony_ci pointer = '*' in ref_pointer_name_seq 741f92157deSopenharmony_ci array = '[' in ref_pointer_name_seq 742f92157deSopenharmony_ci var_type = Type(pos_token.start, pos_token.end, type_name, 743f92157deSopenharmony_ci templated_types, type_modifiers, 744f92157deSopenharmony_ci reference, pointer, array) 745f92157deSopenharmony_ci return VariableDeclaration(pos_token.start, pos_token.end, 746f92157deSopenharmony_ci name, var_type, value, self.namespace_stack) 747f92157deSopenharmony_ci 748f92157deSopenharmony_ci def _GenerateOne(self, token): 749f92157deSopenharmony_ci if token.token_type == tokenize.NAME: 750f92157deSopenharmony_ci if (keywords.IsKeyword(token.name) and 751f92157deSopenharmony_ci not keywords.IsBuiltinType(token.name)): 752f92157deSopenharmony_ci if token.name == 'enum': 753f92157deSopenharmony_ci # Pop the next token and only put it back if it's not 754f92157deSopenharmony_ci # 'class'. This allows us to support the two-token 755f92157deSopenharmony_ci # 'enum class' keyword as if it were simply 'enum'. 756f92157deSopenharmony_ci next = self._GetNextToken() 757f92157deSopenharmony_ci if next.name != 'class': 758f92157deSopenharmony_ci self._AddBackToken(next) 759f92157deSopenharmony_ci 760f92157deSopenharmony_ci method = getattr(self, 'handle_' + token.name) 761f92157deSopenharmony_ci return method() 762f92157deSopenharmony_ci elif token.name == self.in_class_name_only: 763f92157deSopenharmony_ci # The token name is the same as the class, must be a ctor if 764f92157deSopenharmony_ci # there is a paren. Otherwise, it's the return type. 765f92157deSopenharmony_ci # Peek ahead to get the next token to figure out which. 766f92157deSopenharmony_ci next = self._GetNextToken() 767f92157deSopenharmony_ci self._AddBackToken(next) 768f92157deSopenharmony_ci if next.token_type == tokenize.SYNTAX and next.name == '(': 769f92157deSopenharmony_ci return self._GetMethod([token], FUNCTION_CTOR, None, True) 770f92157deSopenharmony_ci # Fall through--handle like any other method. 771f92157deSopenharmony_ci 772f92157deSopenharmony_ci # Handle data or function declaration/definition. 773f92157deSopenharmony_ci syntax = tokenize.SYNTAX 774f92157deSopenharmony_ci temp_tokens, last_token = \ 775f92157deSopenharmony_ci self._GetVarTokensUpToIgnoringTemplates(syntax, 776f92157deSopenharmony_ci '(', ';', '{', '[') 777f92157deSopenharmony_ci temp_tokens.insert(0, token) 778f92157deSopenharmony_ci if last_token.name == '(': 779f92157deSopenharmony_ci # If there is an assignment before the paren, 780f92157deSopenharmony_ci # this is an expression, not a method. 781f92157deSopenharmony_ci expr = bool([e for e in temp_tokens if e.name == '=']) 782f92157deSopenharmony_ci if expr: 783f92157deSopenharmony_ci new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';') 784f92157deSopenharmony_ci temp_tokens.append(last_token) 785f92157deSopenharmony_ci temp_tokens.extend(new_temp) 786f92157deSopenharmony_ci last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0) 787f92157deSopenharmony_ci 788f92157deSopenharmony_ci if last_token.name == '[': 789f92157deSopenharmony_ci # Handle array, this isn't a method, unless it's an operator. 790f92157deSopenharmony_ci # TODO(nnorwitz): keep the size somewhere. 791f92157deSopenharmony_ci # unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']') 792f92157deSopenharmony_ci temp_tokens.append(last_token) 793f92157deSopenharmony_ci if temp_tokens[-2].name == 'operator': 794f92157deSopenharmony_ci temp_tokens.append(self._GetNextToken()) 795f92157deSopenharmony_ci else: 796f92157deSopenharmony_ci temp_tokens2, last_token = \ 797f92157deSopenharmony_ci self._GetVarTokensUpTo(tokenize.SYNTAX, ';') 798f92157deSopenharmony_ci temp_tokens.extend(temp_tokens2) 799f92157deSopenharmony_ci 800f92157deSopenharmony_ci if last_token.name == ';': 801f92157deSopenharmony_ci # Handle data, this isn't a method. 802f92157deSopenharmony_ci parts = self.converter.DeclarationToParts(temp_tokens, True) 803f92157deSopenharmony_ci (name, type_name, templated_types, modifiers, default, 804f92157deSopenharmony_ci unused_other_tokens) = parts 805f92157deSopenharmony_ci 806f92157deSopenharmony_ci t0 = temp_tokens[0] 807f92157deSopenharmony_ci names = [t.name for t in temp_tokens] 808f92157deSopenharmony_ci if templated_types: 809f92157deSopenharmony_ci start, end = self.converter.GetTemplateIndices(names) 810f92157deSopenharmony_ci names = names[:start] + names[end:] 811f92157deSopenharmony_ci default = ''.join([t.name for t in default]) 812f92157deSopenharmony_ci return self._CreateVariable(t0, name, type_name, modifiers, 813f92157deSopenharmony_ci names, templated_types, default) 814f92157deSopenharmony_ci if last_token.name == '{': 815f92157deSopenharmony_ci self._AddBackTokens(temp_tokens[1:]) 816f92157deSopenharmony_ci self._AddBackToken(last_token) 817f92157deSopenharmony_ci method_name = temp_tokens[0].name 818f92157deSopenharmony_ci method = getattr(self, 'handle_' + method_name, None) 819f92157deSopenharmony_ci if not method: 820f92157deSopenharmony_ci # Must be declaring a variable. 821f92157deSopenharmony_ci # TODO(nnorwitz): handle the declaration. 822f92157deSopenharmony_ci return None 823f92157deSopenharmony_ci return method() 824f92157deSopenharmony_ci return self._GetMethod(temp_tokens, 0, None, False) 825f92157deSopenharmony_ci elif token.token_type == tokenize.SYNTAX: 826f92157deSopenharmony_ci if token.name == '~' and self.in_class: 827f92157deSopenharmony_ci # Must be a dtor (probably not in method body). 828f92157deSopenharmony_ci token = self._GetNextToken() 829f92157deSopenharmony_ci # self.in_class can contain A::Name, but the dtor will only 830f92157deSopenharmony_ci # be Name. Make sure to compare against the right value. 831f92157deSopenharmony_ci if (token.token_type == tokenize.NAME and 832f92157deSopenharmony_ci token.name == self.in_class_name_only): 833f92157deSopenharmony_ci return self._GetMethod([token], FUNCTION_DTOR, None, True) 834f92157deSopenharmony_ci # TODO(nnorwitz): handle a lot more syntax. 835f92157deSopenharmony_ci elif token.token_type == tokenize.PREPROCESSOR: 836f92157deSopenharmony_ci # TODO(nnorwitz): handle more preprocessor directives. 837f92157deSopenharmony_ci # token starts with a #, so remove it and strip whitespace. 838f92157deSopenharmony_ci name = token.name[1:].lstrip() 839f92157deSopenharmony_ci if name.startswith('include'): 840f92157deSopenharmony_ci # Remove "include". 841f92157deSopenharmony_ci name = name[7:].strip() 842f92157deSopenharmony_ci assert name 843f92157deSopenharmony_ci # Handle #include \<newline> "header-on-second-line.h". 844f92157deSopenharmony_ci if name.startswith('\\'): 845f92157deSopenharmony_ci name = name[1:].strip() 846f92157deSopenharmony_ci assert name[0] in '<"', token 847f92157deSopenharmony_ci assert name[-1] in '>"', token 848f92157deSopenharmony_ci system = name[0] == '<' 849f92157deSopenharmony_ci filename = name[1:-1] 850f92157deSopenharmony_ci return Include(token.start, token.end, filename, system) 851f92157deSopenharmony_ci if name.startswith('define'): 852f92157deSopenharmony_ci # Remove "define". 853f92157deSopenharmony_ci name = name[6:].strip() 854f92157deSopenharmony_ci assert name 855f92157deSopenharmony_ci value = '' 856f92157deSopenharmony_ci for i, c in enumerate(name): 857f92157deSopenharmony_ci if c.isspace(): 858f92157deSopenharmony_ci value = name[i:].lstrip() 859f92157deSopenharmony_ci name = name[:i] 860f92157deSopenharmony_ci break 861f92157deSopenharmony_ci return Define(token.start, token.end, name, value) 862f92157deSopenharmony_ci if name.startswith('if') and name[2:3].isspace(): 863f92157deSopenharmony_ci condition = name[3:].strip() 864f92157deSopenharmony_ci if condition.startswith('0') or condition.startswith('(0)'): 865f92157deSopenharmony_ci self._SkipIf0Blocks() 866f92157deSopenharmony_ci return None 867f92157deSopenharmony_ci 868f92157deSopenharmony_ci def _GetTokensUpTo(self, expected_token_type, expected_token): 869f92157deSopenharmony_ci return self._GetVarTokensUpTo(expected_token_type, expected_token)[0] 870f92157deSopenharmony_ci 871f92157deSopenharmony_ci def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens): 872f92157deSopenharmony_ci last_token = self._GetNextToken() 873f92157deSopenharmony_ci tokens = [] 874f92157deSopenharmony_ci while (last_token.token_type != expected_token_type or 875f92157deSopenharmony_ci last_token.name not in expected_tokens): 876f92157deSopenharmony_ci tokens.append(last_token) 877f92157deSopenharmony_ci last_token = self._GetNextToken() 878f92157deSopenharmony_ci return tokens, last_token 879f92157deSopenharmony_ci 880f92157deSopenharmony_ci # Same as _GetVarTokensUpTo, but skips over '<...>' which could contain an 881f92157deSopenharmony_ci # expected token. 882f92157deSopenharmony_ci def _GetVarTokensUpToIgnoringTemplates(self, expected_token_type, 883f92157deSopenharmony_ci *expected_tokens): 884f92157deSopenharmony_ci last_token = self._GetNextToken() 885f92157deSopenharmony_ci tokens = [] 886f92157deSopenharmony_ci nesting = 0 887f92157deSopenharmony_ci while (nesting > 0 or 888f92157deSopenharmony_ci last_token.token_type != expected_token_type or 889f92157deSopenharmony_ci last_token.name not in expected_tokens): 890f92157deSopenharmony_ci tokens.append(last_token) 891f92157deSopenharmony_ci last_token = self._GetNextToken() 892f92157deSopenharmony_ci if last_token.name == '<': 893f92157deSopenharmony_ci nesting += 1 894f92157deSopenharmony_ci elif last_token.name == '>': 895f92157deSopenharmony_ci nesting -= 1 896f92157deSopenharmony_ci return tokens, last_token 897f92157deSopenharmony_ci 898f92157deSopenharmony_ci # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necessary. 899f92157deSopenharmony_ci def _IgnoreUpTo(self, token_type, token): 900f92157deSopenharmony_ci unused_tokens = self._GetTokensUpTo(token_type, token) 901f92157deSopenharmony_ci 902f92157deSopenharmony_ci def _SkipIf0Blocks(self): 903f92157deSopenharmony_ci count = 1 904f92157deSopenharmony_ci while 1: 905f92157deSopenharmony_ci token = self._GetNextToken() 906f92157deSopenharmony_ci if token.token_type != tokenize.PREPROCESSOR: 907f92157deSopenharmony_ci continue 908f92157deSopenharmony_ci 909f92157deSopenharmony_ci name = token.name[1:].lstrip() 910f92157deSopenharmony_ci if name.startswith('endif'): 911f92157deSopenharmony_ci count -= 1 912f92157deSopenharmony_ci if count == 0: 913f92157deSopenharmony_ci break 914f92157deSopenharmony_ci elif name.startswith('if'): 915f92157deSopenharmony_ci count += 1 916f92157deSopenharmony_ci 917f92157deSopenharmony_ci def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None): 918f92157deSopenharmony_ci if GetNextToken is None: 919f92157deSopenharmony_ci GetNextToken = self._GetNextToken 920f92157deSopenharmony_ci # Assumes the current token is open_paren and we will consume 921f92157deSopenharmony_ci # and return up to the close_paren. 922f92157deSopenharmony_ci count = 1 923f92157deSopenharmony_ci token = GetNextToken() 924f92157deSopenharmony_ci while 1: 925f92157deSopenharmony_ci if token.token_type == tokenize.SYNTAX: 926f92157deSopenharmony_ci if token.name == open_paren: 927f92157deSopenharmony_ci count += 1 928f92157deSopenharmony_ci elif token.name == close_paren: 929f92157deSopenharmony_ci count -= 1 930f92157deSopenharmony_ci if count == 0: 931f92157deSopenharmony_ci break 932f92157deSopenharmony_ci yield token 933f92157deSopenharmony_ci token = GetNextToken() 934f92157deSopenharmony_ci yield token 935f92157deSopenharmony_ci 936f92157deSopenharmony_ci def _GetParameters(self): 937f92157deSopenharmony_ci return self._GetMatchingChar('(', ')') 938f92157deSopenharmony_ci 939f92157deSopenharmony_ci def GetScope(self): 940f92157deSopenharmony_ci return self._GetMatchingChar('{', '}') 941f92157deSopenharmony_ci 942f92157deSopenharmony_ci def _GetNextToken(self): 943f92157deSopenharmony_ci if self.token_queue: 944f92157deSopenharmony_ci return self.token_queue.pop() 945f92157deSopenharmony_ci try: 946f92157deSopenharmony_ci return next(self.tokens) 947f92157deSopenharmony_ci except StopIteration: 948f92157deSopenharmony_ci return 949f92157deSopenharmony_ci 950f92157deSopenharmony_ci def _AddBackToken(self, token): 951f92157deSopenharmony_ci if token.whence == tokenize.WHENCE_STREAM: 952f92157deSopenharmony_ci token.whence = tokenize.WHENCE_QUEUE 953f92157deSopenharmony_ci self.token_queue.insert(0, token) 954f92157deSopenharmony_ci else: 955f92157deSopenharmony_ci assert token.whence == tokenize.WHENCE_QUEUE, token 956f92157deSopenharmony_ci self.token_queue.append(token) 957f92157deSopenharmony_ci 958f92157deSopenharmony_ci def _AddBackTokens(self, tokens): 959f92157deSopenharmony_ci if tokens: 960f92157deSopenharmony_ci if tokens[-1].whence == tokenize.WHENCE_STREAM: 961f92157deSopenharmony_ci for token in tokens: 962f92157deSopenharmony_ci token.whence = tokenize.WHENCE_QUEUE 963f92157deSopenharmony_ci self.token_queue[:0] = reversed(tokens) 964f92157deSopenharmony_ci else: 965f92157deSopenharmony_ci assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens 966f92157deSopenharmony_ci self.token_queue.extend(reversed(tokens)) 967f92157deSopenharmony_ci 968f92157deSopenharmony_ci def GetName(self, seq=None): 969f92157deSopenharmony_ci """Returns ([tokens], next_token_info).""" 970f92157deSopenharmony_ci GetNextToken = self._GetNextToken 971f92157deSopenharmony_ci if seq is not None: 972f92157deSopenharmony_ci it = iter(seq) 973f92157deSopenharmony_ci GetNextToken = lambda: next(it) 974f92157deSopenharmony_ci next_token = GetNextToken() 975f92157deSopenharmony_ci tokens = [] 976f92157deSopenharmony_ci last_token_was_name = False 977f92157deSopenharmony_ci while (next_token.token_type == tokenize.NAME or 978f92157deSopenharmony_ci (next_token.token_type == tokenize.SYNTAX and 979f92157deSopenharmony_ci next_token.name in ('::', '<'))): 980f92157deSopenharmony_ci # Two NAMEs in a row means the identifier should terminate. 981f92157deSopenharmony_ci # It's probably some sort of variable declaration. 982f92157deSopenharmony_ci if last_token_was_name and next_token.token_type == tokenize.NAME: 983f92157deSopenharmony_ci break 984f92157deSopenharmony_ci last_token_was_name = next_token.token_type == tokenize.NAME 985f92157deSopenharmony_ci tokens.append(next_token) 986f92157deSopenharmony_ci # Handle templated names. 987f92157deSopenharmony_ci if next_token.name == '<': 988f92157deSopenharmony_ci tokens.extend(self._GetMatchingChar('<', '>', GetNextToken)) 989f92157deSopenharmony_ci last_token_was_name = True 990f92157deSopenharmony_ci next_token = GetNextToken() 991f92157deSopenharmony_ci return tokens, next_token 992f92157deSopenharmony_ci 993f92157deSopenharmony_ci def GetMethod(self, modifiers, templated_types): 994f92157deSopenharmony_ci return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') 995f92157deSopenharmony_ci assert len(return_type_and_name) >= 1 996f92157deSopenharmony_ci return self._GetMethod(return_type_and_name, modifiers, templated_types, 997f92157deSopenharmony_ci False) 998f92157deSopenharmony_ci 999f92157deSopenharmony_ci def _GetMethod(self, return_type_and_name, modifiers, templated_types, 1000f92157deSopenharmony_ci get_paren): 1001f92157deSopenharmony_ci template_portion = None 1002f92157deSopenharmony_ci if get_paren: 1003f92157deSopenharmony_ci token = self._GetNextToken() 1004f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1005f92157deSopenharmony_ci if token.name == '<': 1006f92157deSopenharmony_ci # Handle templatized dtors. 1007f92157deSopenharmony_ci template_portion = [token] 1008f92157deSopenharmony_ci template_portion.extend(self._GetMatchingChar('<', '>')) 1009f92157deSopenharmony_ci token = self._GetNextToken() 1010f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1011f92157deSopenharmony_ci assert token.name == '(', token 1012f92157deSopenharmony_ci 1013f92157deSopenharmony_ci name = return_type_and_name.pop() 1014f92157deSopenharmony_ci # Handle templatized ctors. 1015f92157deSopenharmony_ci if name.name == '>': 1016f92157deSopenharmony_ci index = 1 1017f92157deSopenharmony_ci while return_type_and_name[index].name != '<': 1018f92157deSopenharmony_ci index += 1 1019f92157deSopenharmony_ci template_portion = return_type_and_name[index:] + [name] 1020f92157deSopenharmony_ci del return_type_and_name[index:] 1021f92157deSopenharmony_ci name = return_type_and_name.pop() 1022f92157deSopenharmony_ci elif name.name == ']': 1023f92157deSopenharmony_ci rt = return_type_and_name 1024f92157deSopenharmony_ci assert rt[-1].name == '[', return_type_and_name 1025f92157deSopenharmony_ci assert rt[-2].name == 'operator', return_type_and_name 1026f92157deSopenharmony_ci name_seq = return_type_and_name[-2:] 1027f92157deSopenharmony_ci del return_type_and_name[-2:] 1028f92157deSopenharmony_ci name = tokenize.Token(tokenize.NAME, 'operator[]', 1029f92157deSopenharmony_ci name_seq[0].start, name.end) 1030f92157deSopenharmony_ci # Get the open paren so _GetParameters() below works. 1031f92157deSopenharmony_ci unused_open_paren = self._GetNextToken() 1032f92157deSopenharmony_ci 1033f92157deSopenharmony_ci # TODO(nnorwitz): store template_portion. 1034f92157deSopenharmony_ci return_type = return_type_and_name 1035f92157deSopenharmony_ci indices = name 1036f92157deSopenharmony_ci if return_type: 1037f92157deSopenharmony_ci indices = return_type[0] 1038f92157deSopenharmony_ci 1039f92157deSopenharmony_ci # Force ctor for templatized ctors. 1040f92157deSopenharmony_ci if name.name == self.in_class and not modifiers: 1041f92157deSopenharmony_ci modifiers |= FUNCTION_CTOR 1042f92157deSopenharmony_ci parameters = list(self._GetParameters()) 1043f92157deSopenharmony_ci del parameters[-1] # Remove trailing ')'. 1044f92157deSopenharmony_ci 1045f92157deSopenharmony_ci # Handling operator() is especially weird. 1046f92157deSopenharmony_ci if name.name == 'operator' and not parameters: 1047f92157deSopenharmony_ci token = self._GetNextToken() 1048f92157deSopenharmony_ci assert token.name == '(', token 1049f92157deSopenharmony_ci parameters = list(self._GetParameters()) 1050f92157deSopenharmony_ci del parameters[-1] # Remove trailing ')'. 1051f92157deSopenharmony_ci 1052f92157deSopenharmony_ci token = self._GetNextToken() 1053f92157deSopenharmony_ci while token.token_type == tokenize.NAME: 1054f92157deSopenharmony_ci modifier_token = token 1055f92157deSopenharmony_ci token = self._GetNextToken() 1056f92157deSopenharmony_ci if modifier_token.name == 'const': 1057f92157deSopenharmony_ci modifiers |= FUNCTION_CONST 1058f92157deSopenharmony_ci elif modifier_token.name == '__attribute__': 1059f92157deSopenharmony_ci # TODO(nnorwitz): handle more __attribute__ details. 1060f92157deSopenharmony_ci modifiers |= FUNCTION_ATTRIBUTE 1061f92157deSopenharmony_ci assert token.name == '(', token 1062f92157deSopenharmony_ci # Consume everything between the (parens). 1063f92157deSopenharmony_ci unused_tokens = list(self._GetMatchingChar('(', ')')) 1064f92157deSopenharmony_ci token = self._GetNextToken() 1065f92157deSopenharmony_ci elif modifier_token.name == 'throw': 1066f92157deSopenharmony_ci modifiers |= FUNCTION_THROW 1067f92157deSopenharmony_ci assert token.name == '(', token 1068f92157deSopenharmony_ci # Consume everything between the (parens). 1069f92157deSopenharmony_ci unused_tokens = list(self._GetMatchingChar('(', ')')) 1070f92157deSopenharmony_ci token = self._GetNextToken() 1071f92157deSopenharmony_ci elif modifier_token.name == 'override': 1072f92157deSopenharmony_ci modifiers |= FUNCTION_OVERRIDE 1073f92157deSopenharmony_ci elif modifier_token.name == modifier_token.name.upper(): 1074f92157deSopenharmony_ci # HACK(nnorwitz): assume that all upper-case names 1075f92157deSopenharmony_ci # are some macro we aren't expanding. 1076f92157deSopenharmony_ci modifiers |= FUNCTION_UNKNOWN_ANNOTATION 1077f92157deSopenharmony_ci else: 1078f92157deSopenharmony_ci self.HandleError('unexpected token', modifier_token) 1079f92157deSopenharmony_ci 1080f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1081f92157deSopenharmony_ci # Handle ctor initializers. 1082f92157deSopenharmony_ci if token.name == ':': 1083f92157deSopenharmony_ci # TODO(nnorwitz): anything else to handle for initializer list? 1084f92157deSopenharmony_ci while token.name != ';' and token.name != '{': 1085f92157deSopenharmony_ci token = self._GetNextToken() 1086f92157deSopenharmony_ci 1087f92157deSopenharmony_ci # Handle pointer to functions that are really data but look 1088f92157deSopenharmony_ci # like method declarations. 1089f92157deSopenharmony_ci if token.name == '(': 1090f92157deSopenharmony_ci if parameters[0].name == '*': 1091f92157deSopenharmony_ci # name contains the return type. 1092f92157deSopenharmony_ci name = parameters.pop() 1093f92157deSopenharmony_ci # parameters contains the name of the data. 1094f92157deSopenharmony_ci modifiers = [p.name for p in parameters] 1095f92157deSopenharmony_ci # Already at the ( to open the parameter list. 1096f92157deSopenharmony_ci function_parameters = list(self._GetMatchingChar('(', ')')) 1097f92157deSopenharmony_ci del function_parameters[-1] # Remove trailing ')'. 1098f92157deSopenharmony_ci # TODO(nnorwitz): store the function_parameters. 1099f92157deSopenharmony_ci token = self._GetNextToken() 1100f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1101f92157deSopenharmony_ci assert token.name == ';', token 1102f92157deSopenharmony_ci return self._CreateVariable(indices, name.name, indices.name, 1103f92157deSopenharmony_ci modifiers, '', None) 1104f92157deSopenharmony_ci # At this point, we got something like: 1105f92157deSopenharmony_ci # return_type (type::*name_)(params); 1106f92157deSopenharmony_ci # This is a data member called name_ that is a function pointer. 1107f92157deSopenharmony_ci # With this code: void (sq_type::*field_)(string&); 1108f92157deSopenharmony_ci # We get: name=void return_type=[] parameters=sq_type ... field_ 1109f92157deSopenharmony_ci # TODO(nnorwitz): is return_type always empty? 1110f92157deSopenharmony_ci # TODO(nnorwitz): this isn't even close to being correct. 1111f92157deSopenharmony_ci # Just put in something so we don't crash and can move on. 1112f92157deSopenharmony_ci real_name = parameters[-1] 1113f92157deSopenharmony_ci modifiers = [p.name for p in self._GetParameters()] 1114f92157deSopenharmony_ci del modifiers[-1] # Remove trailing ')'. 1115f92157deSopenharmony_ci return self._CreateVariable(indices, real_name.name, indices.name, 1116f92157deSopenharmony_ci modifiers, '', None) 1117f92157deSopenharmony_ci 1118f92157deSopenharmony_ci if token.name == '{': 1119f92157deSopenharmony_ci body = list(self.GetScope()) 1120f92157deSopenharmony_ci del body[-1] # Remove trailing '}'. 1121f92157deSopenharmony_ci else: 1122f92157deSopenharmony_ci body = None 1123f92157deSopenharmony_ci if token.name == '=': 1124f92157deSopenharmony_ci token = self._GetNextToken() 1125f92157deSopenharmony_ci 1126f92157deSopenharmony_ci if token.name == 'default' or token.name == 'delete': 1127f92157deSopenharmony_ci # Ignore explicitly defaulted and deleted special members 1128f92157deSopenharmony_ci # in C++11. 1129f92157deSopenharmony_ci token = self._GetNextToken() 1130f92157deSopenharmony_ci else: 1131f92157deSopenharmony_ci # Handle pure-virtual declarations. 1132f92157deSopenharmony_ci assert token.token_type == tokenize.CONSTANT, token 1133f92157deSopenharmony_ci assert token.name == '0', token 1134f92157deSopenharmony_ci modifiers |= FUNCTION_PURE_VIRTUAL 1135f92157deSopenharmony_ci token = self._GetNextToken() 1136f92157deSopenharmony_ci 1137f92157deSopenharmony_ci if token.name == '[': 1138f92157deSopenharmony_ci # TODO(nnorwitz): store tokens and improve parsing. 1139f92157deSopenharmony_ci # template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N]; 1140f92157deSopenharmony_ci tokens = list(self._GetMatchingChar('[', ']')) 1141f92157deSopenharmony_ci token = self._GetNextToken() 1142f92157deSopenharmony_ci 1143f92157deSopenharmony_ci assert token.name == ';', (token, return_type_and_name, parameters) 1144f92157deSopenharmony_ci 1145f92157deSopenharmony_ci # Looks like we got a method, not a function. 1146f92157deSopenharmony_ci if len(return_type) > 2 and return_type[-1].name == '::': 1147f92157deSopenharmony_ci return_type, in_class = \ 1148f92157deSopenharmony_ci self._GetReturnTypeAndClassName(return_type) 1149f92157deSopenharmony_ci return Method(indices.start, indices.end, name.name, in_class, 1150f92157deSopenharmony_ci return_type, parameters, modifiers, templated_types, 1151f92157deSopenharmony_ci body, self.namespace_stack) 1152f92157deSopenharmony_ci return Function(indices.start, indices.end, name.name, return_type, 1153f92157deSopenharmony_ci parameters, modifiers, templated_types, body, 1154f92157deSopenharmony_ci self.namespace_stack) 1155f92157deSopenharmony_ci 1156f92157deSopenharmony_ci def _GetReturnTypeAndClassName(self, token_seq): 1157f92157deSopenharmony_ci # Splitting the return type from the class name in a method 1158f92157deSopenharmony_ci # can be tricky. For example, Return::Type::Is::Hard::To::Find(). 1159f92157deSopenharmony_ci # Where is the return type and where is the class name? 1160f92157deSopenharmony_ci # The heuristic used is to pull the last name as the class name. 1161f92157deSopenharmony_ci # This includes all the templated type info. 1162f92157deSopenharmony_ci # TODO(nnorwitz): if there is only One name like in the 1163f92157deSopenharmony_ci # example above, punt and assume the last bit is the class name. 1164f92157deSopenharmony_ci 1165f92157deSopenharmony_ci # Ignore a :: prefix, if exists so we can find the first real name. 1166f92157deSopenharmony_ci i = 0 1167f92157deSopenharmony_ci if token_seq[0].name == '::': 1168f92157deSopenharmony_ci i = 1 1169f92157deSopenharmony_ci # Ignore a :: suffix, if exists. 1170f92157deSopenharmony_ci end = len(token_seq) - 1 1171f92157deSopenharmony_ci if token_seq[end-1].name == '::': 1172f92157deSopenharmony_ci end -= 1 1173f92157deSopenharmony_ci 1174f92157deSopenharmony_ci # Make a copy of the sequence so we can append a sentinel 1175f92157deSopenharmony_ci # value. This is required for GetName will has to have some 1176f92157deSopenharmony_ci # terminating condition beyond the last name. 1177f92157deSopenharmony_ci seq_copy = token_seq[i:end] 1178f92157deSopenharmony_ci seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0)) 1179f92157deSopenharmony_ci names = [] 1180f92157deSopenharmony_ci while i < end: 1181f92157deSopenharmony_ci # Iterate through the sequence parsing out each name. 1182f92157deSopenharmony_ci new_name, next = self.GetName(seq_copy[i:]) 1183f92157deSopenharmony_ci assert new_name, 'Got empty new_name, next=%s' % next 1184f92157deSopenharmony_ci # We got a pointer or ref. Add it to the name. 1185f92157deSopenharmony_ci if next and next.token_type == tokenize.SYNTAX: 1186f92157deSopenharmony_ci new_name.append(next) 1187f92157deSopenharmony_ci names.append(new_name) 1188f92157deSopenharmony_ci i += len(new_name) 1189f92157deSopenharmony_ci 1190f92157deSopenharmony_ci # Now that we have the names, it's time to undo what we did. 1191f92157deSopenharmony_ci 1192f92157deSopenharmony_ci # Remove the sentinel value. 1193f92157deSopenharmony_ci names[-1].pop() 1194f92157deSopenharmony_ci # Flatten the token sequence for the return type. 1195f92157deSopenharmony_ci return_type = [e for seq in names[:-1] for e in seq] 1196f92157deSopenharmony_ci # The class name is the last name. 1197f92157deSopenharmony_ci class_name = names[-1] 1198f92157deSopenharmony_ci return return_type, class_name 1199f92157deSopenharmony_ci 1200f92157deSopenharmony_ci def handle_bool(self): 1201f92157deSopenharmony_ci pass 1202f92157deSopenharmony_ci 1203f92157deSopenharmony_ci def handle_char(self): 1204f92157deSopenharmony_ci pass 1205f92157deSopenharmony_ci 1206f92157deSopenharmony_ci def handle_int(self): 1207f92157deSopenharmony_ci pass 1208f92157deSopenharmony_ci 1209f92157deSopenharmony_ci def handle_long(self): 1210f92157deSopenharmony_ci pass 1211f92157deSopenharmony_ci 1212f92157deSopenharmony_ci def handle_short(self): 1213f92157deSopenharmony_ci pass 1214f92157deSopenharmony_ci 1215f92157deSopenharmony_ci def handle_double(self): 1216f92157deSopenharmony_ci pass 1217f92157deSopenharmony_ci 1218f92157deSopenharmony_ci def handle_float(self): 1219f92157deSopenharmony_ci pass 1220f92157deSopenharmony_ci 1221f92157deSopenharmony_ci def handle_void(self): 1222f92157deSopenharmony_ci pass 1223f92157deSopenharmony_ci 1224f92157deSopenharmony_ci def handle_wchar_t(self): 1225f92157deSopenharmony_ci pass 1226f92157deSopenharmony_ci 1227f92157deSopenharmony_ci def handle_unsigned(self): 1228f92157deSopenharmony_ci pass 1229f92157deSopenharmony_ci 1230f92157deSopenharmony_ci def handle_signed(self): 1231f92157deSopenharmony_ci pass 1232f92157deSopenharmony_ci 1233f92157deSopenharmony_ci def _GetNestedType(self, ctor): 1234f92157deSopenharmony_ci name = None 1235f92157deSopenharmony_ci name_tokens, token = self.GetName() 1236f92157deSopenharmony_ci if name_tokens: 1237f92157deSopenharmony_ci name = ''.join([t.name for t in name_tokens]) 1238f92157deSopenharmony_ci 1239f92157deSopenharmony_ci # Handle forward declarations. 1240f92157deSopenharmony_ci if token.token_type == tokenize.SYNTAX and token.name == ';': 1241f92157deSopenharmony_ci return ctor(token.start, token.end, name, None, 1242f92157deSopenharmony_ci self.namespace_stack) 1243f92157deSopenharmony_ci 1244f92157deSopenharmony_ci if token.token_type == tokenize.NAME and self._handling_typedef: 1245f92157deSopenharmony_ci self._AddBackToken(token) 1246f92157deSopenharmony_ci return ctor(token.start, token.end, name, None, 1247f92157deSopenharmony_ci self.namespace_stack) 1248f92157deSopenharmony_ci 1249f92157deSopenharmony_ci # Must be the type declaration. 1250f92157deSopenharmony_ci fields = list(self._GetMatchingChar('{', '}')) 1251f92157deSopenharmony_ci del fields[-1] # Remove trailing '}'. 1252f92157deSopenharmony_ci if token.token_type == tokenize.SYNTAX and token.name == '{': 1253f92157deSopenharmony_ci next = self._GetNextToken() 1254f92157deSopenharmony_ci new_type = ctor(token.start, token.end, name, fields, 1255f92157deSopenharmony_ci self.namespace_stack) 1256f92157deSopenharmony_ci # A name means this is an anonymous type and the name 1257f92157deSopenharmony_ci # is the variable declaration. 1258f92157deSopenharmony_ci if next.token_type != tokenize.NAME: 1259f92157deSopenharmony_ci return new_type 1260f92157deSopenharmony_ci name = new_type 1261f92157deSopenharmony_ci token = next 1262f92157deSopenharmony_ci 1263f92157deSopenharmony_ci # Must be variable declaration using the type prefixed with keyword. 1264f92157deSopenharmony_ci assert token.token_type == tokenize.NAME, token 1265f92157deSopenharmony_ci return self._CreateVariable(token, token.name, name, [], '', None) 1266f92157deSopenharmony_ci 1267f92157deSopenharmony_ci def handle_struct(self): 1268f92157deSopenharmony_ci # Special case the handling typedef/aliasing of structs here. 1269f92157deSopenharmony_ci # It would be a pain to handle in the class code. 1270f92157deSopenharmony_ci name_tokens, var_token = self.GetName() 1271f92157deSopenharmony_ci if name_tokens: 1272f92157deSopenharmony_ci next_token = self._GetNextToken() 1273f92157deSopenharmony_ci is_syntax = (var_token.token_type == tokenize.SYNTAX and 1274f92157deSopenharmony_ci var_token.name[0] in '*&') 1275f92157deSopenharmony_ci is_variable = (var_token.token_type == tokenize.NAME and 1276f92157deSopenharmony_ci next_token.name == ';') 1277f92157deSopenharmony_ci variable = var_token 1278f92157deSopenharmony_ci if is_syntax and not is_variable: 1279f92157deSopenharmony_ci variable = next_token 1280f92157deSopenharmony_ci temp = self._GetNextToken() 1281f92157deSopenharmony_ci if temp.token_type == tokenize.SYNTAX and temp.name == '(': 1282f92157deSopenharmony_ci # Handle methods declared to return a struct. 1283f92157deSopenharmony_ci t0 = name_tokens[0] 1284f92157deSopenharmony_ci struct = tokenize.Token(tokenize.NAME, 'struct', 1285f92157deSopenharmony_ci t0.start-7, t0.start-2) 1286f92157deSopenharmony_ci type_and_name = [struct] 1287f92157deSopenharmony_ci type_and_name.extend(name_tokens) 1288f92157deSopenharmony_ci type_and_name.extend((var_token, next_token)) 1289f92157deSopenharmony_ci return self._GetMethod(type_and_name, 0, None, False) 1290f92157deSopenharmony_ci assert temp.name == ';', (temp, name_tokens, var_token) 1291f92157deSopenharmony_ci if is_syntax or (is_variable and not self._handling_typedef): 1292f92157deSopenharmony_ci modifiers = ['struct'] 1293f92157deSopenharmony_ci type_name = ''.join([t.name for t in name_tokens]) 1294f92157deSopenharmony_ci position = name_tokens[0] 1295f92157deSopenharmony_ci return self._CreateVariable(position, variable.name, type_name, 1296f92157deSopenharmony_ci modifiers, var_token.name, None) 1297f92157deSopenharmony_ci name_tokens.extend((var_token, next_token)) 1298f92157deSopenharmony_ci self._AddBackTokens(name_tokens) 1299f92157deSopenharmony_ci else: 1300f92157deSopenharmony_ci self._AddBackToken(var_token) 1301f92157deSopenharmony_ci return self._GetClass(Struct, VISIBILITY_PUBLIC, None) 1302f92157deSopenharmony_ci 1303f92157deSopenharmony_ci def handle_union(self): 1304f92157deSopenharmony_ci return self._GetNestedType(Union) 1305f92157deSopenharmony_ci 1306f92157deSopenharmony_ci def handle_enum(self): 1307f92157deSopenharmony_ci return self._GetNestedType(Enum) 1308f92157deSopenharmony_ci 1309f92157deSopenharmony_ci def handle_auto(self): 1310f92157deSopenharmony_ci # TODO(nnorwitz): warn about using auto? Probably not since it 1311f92157deSopenharmony_ci # will be reclaimed and useful for C++0x. 1312f92157deSopenharmony_ci pass 1313f92157deSopenharmony_ci 1314f92157deSopenharmony_ci def handle_register(self): 1315f92157deSopenharmony_ci pass 1316f92157deSopenharmony_ci 1317f92157deSopenharmony_ci def handle_const(self): 1318f92157deSopenharmony_ci pass 1319f92157deSopenharmony_ci 1320f92157deSopenharmony_ci def handle_inline(self): 1321f92157deSopenharmony_ci pass 1322f92157deSopenharmony_ci 1323f92157deSopenharmony_ci def handle_extern(self): 1324f92157deSopenharmony_ci pass 1325f92157deSopenharmony_ci 1326f92157deSopenharmony_ci def handle_static(self): 1327f92157deSopenharmony_ci pass 1328f92157deSopenharmony_ci 1329f92157deSopenharmony_ci def handle_virtual(self): 1330f92157deSopenharmony_ci # What follows must be a method. 1331f92157deSopenharmony_ci token = token2 = self._GetNextToken() 1332f92157deSopenharmony_ci if token.name == 'inline': 1333f92157deSopenharmony_ci # HACK(nnorwitz): handle inline dtors by ignoring 'inline'. 1334f92157deSopenharmony_ci token2 = self._GetNextToken() 1335f92157deSopenharmony_ci if token2.token_type == tokenize.SYNTAX and token2.name == '~': 1336f92157deSopenharmony_ci return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None) 1337f92157deSopenharmony_ci assert token.token_type == tokenize.NAME or token.name == '::', token 1338f92157deSopenharmony_ci return_type_and_name, _ = self._GetVarTokensUpToIgnoringTemplates( 1339f92157deSopenharmony_ci tokenize.SYNTAX, '(') # ) 1340f92157deSopenharmony_ci return_type_and_name.insert(0, token) 1341f92157deSopenharmony_ci if token2 is not token: 1342f92157deSopenharmony_ci return_type_and_name.insert(1, token2) 1343f92157deSopenharmony_ci return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL, 1344f92157deSopenharmony_ci None, False) 1345f92157deSopenharmony_ci 1346f92157deSopenharmony_ci def handle_volatile(self): 1347f92157deSopenharmony_ci pass 1348f92157deSopenharmony_ci 1349f92157deSopenharmony_ci def handle_mutable(self): 1350f92157deSopenharmony_ci pass 1351f92157deSopenharmony_ci 1352f92157deSopenharmony_ci def handle_public(self): 1353f92157deSopenharmony_ci assert self.in_class 1354f92157deSopenharmony_ci self.visibility = VISIBILITY_PUBLIC 1355f92157deSopenharmony_ci 1356f92157deSopenharmony_ci def handle_protected(self): 1357f92157deSopenharmony_ci assert self.in_class 1358f92157deSopenharmony_ci self.visibility = VISIBILITY_PROTECTED 1359f92157deSopenharmony_ci 1360f92157deSopenharmony_ci def handle_private(self): 1361f92157deSopenharmony_ci assert self.in_class 1362f92157deSopenharmony_ci self.visibility = VISIBILITY_PRIVATE 1363f92157deSopenharmony_ci 1364f92157deSopenharmony_ci def handle_friend(self): 1365f92157deSopenharmony_ci tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 1366f92157deSopenharmony_ci assert tokens 1367f92157deSopenharmony_ci t0 = tokens[0] 1368f92157deSopenharmony_ci return Friend(t0.start, t0.end, tokens, self.namespace_stack) 1369f92157deSopenharmony_ci 1370f92157deSopenharmony_ci def handle_static_cast(self): 1371f92157deSopenharmony_ci pass 1372f92157deSopenharmony_ci 1373f92157deSopenharmony_ci def handle_const_cast(self): 1374f92157deSopenharmony_ci pass 1375f92157deSopenharmony_ci 1376f92157deSopenharmony_ci def handle_dynamic_cast(self): 1377f92157deSopenharmony_ci pass 1378f92157deSopenharmony_ci 1379f92157deSopenharmony_ci def handle_reinterpret_cast(self): 1380f92157deSopenharmony_ci pass 1381f92157deSopenharmony_ci 1382f92157deSopenharmony_ci def handle_new(self): 1383f92157deSopenharmony_ci pass 1384f92157deSopenharmony_ci 1385f92157deSopenharmony_ci def handle_delete(self): 1386f92157deSopenharmony_ci tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 1387f92157deSopenharmony_ci assert tokens 1388f92157deSopenharmony_ci return Delete(tokens[0].start, tokens[0].end, tokens) 1389f92157deSopenharmony_ci 1390f92157deSopenharmony_ci def handle_typedef(self): 1391f92157deSopenharmony_ci token = self._GetNextToken() 1392f92157deSopenharmony_ci if (token.token_type == tokenize.NAME and 1393f92157deSopenharmony_ci keywords.IsKeyword(token.name)): 1394f92157deSopenharmony_ci # Token must be struct/enum/union/class. 1395f92157deSopenharmony_ci method = getattr(self, 'handle_' + token.name) 1396f92157deSopenharmony_ci self._handling_typedef = True 1397f92157deSopenharmony_ci tokens = [method()] 1398f92157deSopenharmony_ci self._handling_typedef = False 1399f92157deSopenharmony_ci else: 1400f92157deSopenharmony_ci tokens = [token] 1401f92157deSopenharmony_ci 1402f92157deSopenharmony_ci # Get the remainder of the typedef up to the semi-colon. 1403f92157deSopenharmony_ci tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';')) 1404f92157deSopenharmony_ci 1405f92157deSopenharmony_ci # TODO(nnorwitz): clean all this up. 1406f92157deSopenharmony_ci assert tokens 1407f92157deSopenharmony_ci name = tokens.pop() 1408f92157deSopenharmony_ci indices = name 1409f92157deSopenharmony_ci if tokens: 1410f92157deSopenharmony_ci indices = tokens[0] 1411f92157deSopenharmony_ci if not indices: 1412f92157deSopenharmony_ci indices = token 1413f92157deSopenharmony_ci if name.name == ')': 1414f92157deSopenharmony_ci # HACK(nnorwitz): Handle pointers to functions "properly". 1415f92157deSopenharmony_ci if (len(tokens) >= 4 and 1416f92157deSopenharmony_ci tokens[1].name == '(' and tokens[2].name == '*'): 1417f92157deSopenharmony_ci tokens.append(name) 1418f92157deSopenharmony_ci name = tokens[3] 1419f92157deSopenharmony_ci elif name.name == ']': 1420f92157deSopenharmony_ci # HACK(nnorwitz): Handle arrays properly. 1421f92157deSopenharmony_ci if len(tokens) >= 2: 1422f92157deSopenharmony_ci tokens.append(name) 1423f92157deSopenharmony_ci name = tokens[1] 1424f92157deSopenharmony_ci new_type = tokens 1425f92157deSopenharmony_ci if tokens and isinstance(tokens[0], tokenize.Token): 1426f92157deSopenharmony_ci new_type = self.converter.ToType(tokens)[0] 1427f92157deSopenharmony_ci return Typedef(indices.start, indices.end, name.name, 1428f92157deSopenharmony_ci new_type, self.namespace_stack) 1429f92157deSopenharmony_ci 1430f92157deSopenharmony_ci def handle_typeid(self): 1431f92157deSopenharmony_ci pass # Not needed yet. 1432f92157deSopenharmony_ci 1433f92157deSopenharmony_ci def handle_typename(self): 1434f92157deSopenharmony_ci pass # Not needed yet. 1435f92157deSopenharmony_ci 1436f92157deSopenharmony_ci def _GetTemplatedTypes(self): 1437f92157deSopenharmony_ci result = collections.OrderedDict() 1438f92157deSopenharmony_ci tokens = list(self._GetMatchingChar('<', '>')) 1439f92157deSopenharmony_ci len_tokens = len(tokens) - 1 # Ignore trailing '>'. 1440f92157deSopenharmony_ci i = 0 1441f92157deSopenharmony_ci while i < len_tokens: 1442f92157deSopenharmony_ci key = tokens[i].name 1443f92157deSopenharmony_ci i += 1 1444f92157deSopenharmony_ci if keywords.IsKeyword(key) or key == ',': 1445f92157deSopenharmony_ci continue 1446f92157deSopenharmony_ci type_name = default = None 1447f92157deSopenharmony_ci if i < len_tokens: 1448f92157deSopenharmony_ci i += 1 1449f92157deSopenharmony_ci if tokens[i-1].name == '=': 1450f92157deSopenharmony_ci assert i < len_tokens, '%s %s' % (i, tokens) 1451f92157deSopenharmony_ci default, unused_next_token = self.GetName(tokens[i:]) 1452f92157deSopenharmony_ci i += len(default) 1453f92157deSopenharmony_ci else: 1454f92157deSopenharmony_ci if tokens[i-1].name != ',': 1455f92157deSopenharmony_ci # We got something like: Type variable. 1456f92157deSopenharmony_ci # Re-adjust the key (variable) and type_name (Type). 1457f92157deSopenharmony_ci key = tokens[i-1].name 1458f92157deSopenharmony_ci type_name = tokens[i-2] 1459f92157deSopenharmony_ci 1460f92157deSopenharmony_ci result[key] = (type_name, default) 1461f92157deSopenharmony_ci return result 1462f92157deSopenharmony_ci 1463f92157deSopenharmony_ci def handle_template(self): 1464f92157deSopenharmony_ci token = self._GetNextToken() 1465f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1466f92157deSopenharmony_ci assert token.name == '<', token 1467f92157deSopenharmony_ci templated_types = self._GetTemplatedTypes() 1468f92157deSopenharmony_ci # TODO(nnorwitz): for now, just ignore the template params. 1469f92157deSopenharmony_ci token = self._GetNextToken() 1470f92157deSopenharmony_ci if token.token_type == tokenize.NAME: 1471f92157deSopenharmony_ci if token.name == 'class': 1472f92157deSopenharmony_ci return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types) 1473f92157deSopenharmony_ci elif token.name == 'struct': 1474f92157deSopenharmony_ci return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types) 1475f92157deSopenharmony_ci elif token.name == 'friend': 1476f92157deSopenharmony_ci return self.handle_friend() 1477f92157deSopenharmony_ci self._AddBackToken(token) 1478f92157deSopenharmony_ci tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';') 1479f92157deSopenharmony_ci tokens.append(last) 1480f92157deSopenharmony_ci self._AddBackTokens(tokens) 1481f92157deSopenharmony_ci if last.name == '(': 1482f92157deSopenharmony_ci return self.GetMethod(FUNCTION_NONE, templated_types) 1483f92157deSopenharmony_ci # Must be a variable definition. 1484f92157deSopenharmony_ci return None 1485f92157deSopenharmony_ci 1486f92157deSopenharmony_ci def handle_true(self): 1487f92157deSopenharmony_ci pass # Nothing to do. 1488f92157deSopenharmony_ci 1489f92157deSopenharmony_ci def handle_false(self): 1490f92157deSopenharmony_ci pass # Nothing to do. 1491f92157deSopenharmony_ci 1492f92157deSopenharmony_ci def handle_asm(self): 1493f92157deSopenharmony_ci pass # Not needed yet. 1494f92157deSopenharmony_ci 1495f92157deSopenharmony_ci def handle_class(self): 1496f92157deSopenharmony_ci return self._GetClass(Class, VISIBILITY_PRIVATE, None) 1497f92157deSopenharmony_ci 1498f92157deSopenharmony_ci def _GetBases(self): 1499f92157deSopenharmony_ci # Get base classes. 1500f92157deSopenharmony_ci bases = [] 1501f92157deSopenharmony_ci while 1: 1502f92157deSopenharmony_ci token = self._GetNextToken() 1503f92157deSopenharmony_ci assert token.token_type == tokenize.NAME, token 1504f92157deSopenharmony_ci # TODO(nnorwitz): store kind of inheritance...maybe. 1505f92157deSopenharmony_ci if token.name not in ('public', 'protected', 'private'): 1506f92157deSopenharmony_ci # If inheritance type is not specified, it is private. 1507f92157deSopenharmony_ci # Just put the token back so we can form a name. 1508f92157deSopenharmony_ci # TODO(nnorwitz): it would be good to warn about this. 1509f92157deSopenharmony_ci self._AddBackToken(token) 1510f92157deSopenharmony_ci else: 1511f92157deSopenharmony_ci # Check for virtual inheritance. 1512f92157deSopenharmony_ci token = self._GetNextToken() 1513f92157deSopenharmony_ci if token.name != 'virtual': 1514f92157deSopenharmony_ci self._AddBackToken(token) 1515f92157deSopenharmony_ci else: 1516f92157deSopenharmony_ci # TODO(nnorwitz): store that we got virtual for this base. 1517f92157deSopenharmony_ci pass 1518f92157deSopenharmony_ci base, next_token = self.GetName() 1519f92157deSopenharmony_ci bases_ast = self.converter.ToType(base) 1520f92157deSopenharmony_ci assert len(bases_ast) == 1, bases_ast 1521f92157deSopenharmony_ci bases.append(bases_ast[0]) 1522f92157deSopenharmony_ci assert next_token.token_type == tokenize.SYNTAX, next_token 1523f92157deSopenharmony_ci if next_token.name == '{': 1524f92157deSopenharmony_ci token = next_token 1525f92157deSopenharmony_ci break 1526f92157deSopenharmony_ci # Support multiple inheritance. 1527f92157deSopenharmony_ci assert next_token.name == ',', next_token 1528f92157deSopenharmony_ci return bases, token 1529f92157deSopenharmony_ci 1530f92157deSopenharmony_ci def _GetClass(self, class_type, visibility, templated_types): 1531f92157deSopenharmony_ci class_name = None 1532f92157deSopenharmony_ci class_token = self._GetNextToken() 1533f92157deSopenharmony_ci if class_token.token_type != tokenize.NAME: 1534f92157deSopenharmony_ci assert class_token.token_type == tokenize.SYNTAX, class_token 1535f92157deSopenharmony_ci token = class_token 1536f92157deSopenharmony_ci else: 1537f92157deSopenharmony_ci # Skip any macro (e.g. storage class specifiers) after the 1538f92157deSopenharmony_ci # 'class' keyword. 1539f92157deSopenharmony_ci next_token = self._GetNextToken() 1540f92157deSopenharmony_ci if next_token.token_type == tokenize.NAME: 1541f92157deSopenharmony_ci self._AddBackToken(next_token) 1542f92157deSopenharmony_ci else: 1543f92157deSopenharmony_ci self._AddBackTokens([class_token, next_token]) 1544f92157deSopenharmony_ci name_tokens, token = self.GetName() 1545f92157deSopenharmony_ci class_name = ''.join([t.name for t in name_tokens]) 1546f92157deSopenharmony_ci bases = None 1547f92157deSopenharmony_ci if token.token_type == tokenize.SYNTAX: 1548f92157deSopenharmony_ci if token.name == ';': 1549f92157deSopenharmony_ci # Forward declaration. 1550f92157deSopenharmony_ci return class_type(class_token.start, class_token.end, 1551f92157deSopenharmony_ci class_name, None, templated_types, None, 1552f92157deSopenharmony_ci self.namespace_stack) 1553f92157deSopenharmony_ci if token.name in '*&': 1554f92157deSopenharmony_ci # Inline forward declaration. Could be method or data. 1555f92157deSopenharmony_ci name_token = self._GetNextToken() 1556f92157deSopenharmony_ci next_token = self._GetNextToken() 1557f92157deSopenharmony_ci if next_token.name == ';': 1558f92157deSopenharmony_ci # Handle data 1559f92157deSopenharmony_ci modifiers = ['class'] 1560f92157deSopenharmony_ci return self._CreateVariable(class_token, name_token.name, 1561f92157deSopenharmony_ci class_name, 1562f92157deSopenharmony_ci modifiers, token.name, None) 1563f92157deSopenharmony_ci else: 1564f92157deSopenharmony_ci # Assume this is a method. 1565f92157deSopenharmony_ci tokens = (class_token, token, name_token, next_token) 1566f92157deSopenharmony_ci self._AddBackTokens(tokens) 1567f92157deSopenharmony_ci return self.GetMethod(FUNCTION_NONE, None) 1568f92157deSopenharmony_ci if token.name == ':': 1569f92157deSopenharmony_ci bases, token = self._GetBases() 1570f92157deSopenharmony_ci 1571f92157deSopenharmony_ci body = None 1572f92157deSopenharmony_ci if token.token_type == tokenize.SYNTAX and token.name == '{': 1573f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1574f92157deSopenharmony_ci assert token.name == '{', token 1575f92157deSopenharmony_ci 1576f92157deSopenharmony_ci ast = AstBuilder(self.GetScope(), self.filename, class_name, 1577f92157deSopenharmony_ci visibility, self.namespace_stack) 1578f92157deSopenharmony_ci body = list(ast.Generate()) 1579f92157deSopenharmony_ci 1580f92157deSopenharmony_ci if not self._handling_typedef: 1581f92157deSopenharmony_ci token = self._GetNextToken() 1582f92157deSopenharmony_ci if token.token_type != tokenize.NAME: 1583f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1584f92157deSopenharmony_ci assert token.name == ';', token 1585f92157deSopenharmony_ci else: 1586f92157deSopenharmony_ci new_class = class_type(class_token.start, class_token.end, 1587f92157deSopenharmony_ci class_name, bases, None, 1588f92157deSopenharmony_ci body, self.namespace_stack) 1589f92157deSopenharmony_ci 1590f92157deSopenharmony_ci modifiers = [] 1591f92157deSopenharmony_ci return self._CreateVariable(class_token, 1592f92157deSopenharmony_ci token.name, new_class, 1593f92157deSopenharmony_ci modifiers, token.name, None) 1594f92157deSopenharmony_ci else: 1595f92157deSopenharmony_ci if not self._handling_typedef: 1596f92157deSopenharmony_ci self.HandleError('non-typedef token', token) 1597f92157deSopenharmony_ci self._AddBackToken(token) 1598f92157deSopenharmony_ci 1599f92157deSopenharmony_ci return class_type(class_token.start, class_token.end, class_name, 1600f92157deSopenharmony_ci bases, templated_types, body, self.namespace_stack) 1601f92157deSopenharmony_ci 1602f92157deSopenharmony_ci def handle_namespace(self): 1603f92157deSopenharmony_ci # Support anonymous namespaces. 1604f92157deSopenharmony_ci name = None 1605f92157deSopenharmony_ci name_tokens, token = self.GetName() 1606f92157deSopenharmony_ci if name_tokens: 1607f92157deSopenharmony_ci name = ''.join([t.name for t in name_tokens]) 1608f92157deSopenharmony_ci self.namespace_stack.append(name) 1609f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX, token 1610f92157deSopenharmony_ci # Create an internal token that denotes when the namespace is complete. 1611f92157deSopenharmony_ci internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP, 1612f92157deSopenharmony_ci None, None) 1613f92157deSopenharmony_ci internal_token.whence = token.whence 1614f92157deSopenharmony_ci if token.name == '=': 1615f92157deSopenharmony_ci # TODO(nnorwitz): handle aliasing namespaces. 1616f92157deSopenharmony_ci name, next_token = self.GetName() 1617f92157deSopenharmony_ci assert next_token.name == ';', next_token 1618f92157deSopenharmony_ci self._AddBackToken(internal_token) 1619f92157deSopenharmony_ci else: 1620f92157deSopenharmony_ci assert token.name == '{', token 1621f92157deSopenharmony_ci tokens = list(self.GetScope()) 1622f92157deSopenharmony_ci # Replace the trailing } with the internal namespace pop token. 1623f92157deSopenharmony_ci tokens[-1] = internal_token 1624f92157deSopenharmony_ci # Handle namespace with nothing in it. 1625f92157deSopenharmony_ci self._AddBackTokens(tokens) 1626f92157deSopenharmony_ci return None 1627f92157deSopenharmony_ci 1628f92157deSopenharmony_ci def handle_using(self): 1629f92157deSopenharmony_ci tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 1630f92157deSopenharmony_ci assert tokens 1631f92157deSopenharmony_ci return Using(tokens[0].start, tokens[0].end, tokens) 1632f92157deSopenharmony_ci 1633f92157deSopenharmony_ci def handle_explicit(self): 1634f92157deSopenharmony_ci assert self.in_class 1635f92157deSopenharmony_ci # Nothing much to do. 1636f92157deSopenharmony_ci # TODO(nnorwitz): maybe verify the method name == class name. 1637f92157deSopenharmony_ci # This must be a ctor. 1638f92157deSopenharmony_ci return self.GetMethod(FUNCTION_CTOR, None) 1639f92157deSopenharmony_ci 1640f92157deSopenharmony_ci def handle_this(self): 1641f92157deSopenharmony_ci pass # Nothing to do. 1642f92157deSopenharmony_ci 1643f92157deSopenharmony_ci def handle_operator(self): 1644f92157deSopenharmony_ci # Pull off the next token(s?) and make that part of the method name. 1645f92157deSopenharmony_ci pass 1646f92157deSopenharmony_ci 1647f92157deSopenharmony_ci def handle_sizeof(self): 1648f92157deSopenharmony_ci pass 1649f92157deSopenharmony_ci 1650f92157deSopenharmony_ci def handle_case(self): 1651f92157deSopenharmony_ci pass 1652f92157deSopenharmony_ci 1653f92157deSopenharmony_ci def handle_switch(self): 1654f92157deSopenharmony_ci pass 1655f92157deSopenharmony_ci 1656f92157deSopenharmony_ci def handle_default(self): 1657f92157deSopenharmony_ci token = self._GetNextToken() 1658f92157deSopenharmony_ci assert token.token_type == tokenize.SYNTAX 1659f92157deSopenharmony_ci assert token.name == ':' 1660f92157deSopenharmony_ci 1661f92157deSopenharmony_ci def handle_if(self): 1662f92157deSopenharmony_ci pass 1663f92157deSopenharmony_ci 1664f92157deSopenharmony_ci def handle_else(self): 1665f92157deSopenharmony_ci pass 1666f92157deSopenharmony_ci 1667f92157deSopenharmony_ci def handle_return(self): 1668f92157deSopenharmony_ci tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 1669f92157deSopenharmony_ci if not tokens: 1670f92157deSopenharmony_ci return Return(self.current_token.start, self.current_token.end, None) 1671f92157deSopenharmony_ci return Return(tokens[0].start, tokens[0].end, tokens) 1672f92157deSopenharmony_ci 1673f92157deSopenharmony_ci def handle_goto(self): 1674f92157deSopenharmony_ci tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') 1675f92157deSopenharmony_ci assert len(tokens) == 1, str(tokens) 1676f92157deSopenharmony_ci return Goto(tokens[0].start, tokens[0].end, tokens[0].name) 1677f92157deSopenharmony_ci 1678f92157deSopenharmony_ci def handle_try(self): 1679f92157deSopenharmony_ci pass # Not needed yet. 1680f92157deSopenharmony_ci 1681f92157deSopenharmony_ci def handle_catch(self): 1682f92157deSopenharmony_ci pass # Not needed yet. 1683f92157deSopenharmony_ci 1684f92157deSopenharmony_ci def handle_throw(self): 1685f92157deSopenharmony_ci pass # Not needed yet. 1686f92157deSopenharmony_ci 1687f92157deSopenharmony_ci def handle_while(self): 1688f92157deSopenharmony_ci pass 1689f92157deSopenharmony_ci 1690f92157deSopenharmony_ci def handle_do(self): 1691f92157deSopenharmony_ci pass 1692f92157deSopenharmony_ci 1693f92157deSopenharmony_ci def handle_for(self): 1694f92157deSopenharmony_ci pass 1695f92157deSopenharmony_ci 1696f92157deSopenharmony_ci def handle_break(self): 1697f92157deSopenharmony_ci self._IgnoreUpTo(tokenize.SYNTAX, ';') 1698f92157deSopenharmony_ci 1699f92157deSopenharmony_ci def handle_continue(self): 1700f92157deSopenharmony_ci self._IgnoreUpTo(tokenize.SYNTAX, ';') 1701f92157deSopenharmony_ci 1702f92157deSopenharmony_ci 1703f92157deSopenharmony_cidef BuilderFromSource(source, filename): 1704f92157deSopenharmony_ci """Utility method that returns an AstBuilder from source code. 1705f92157deSopenharmony_ci 1706f92157deSopenharmony_ci Args: 1707f92157deSopenharmony_ci source: 'C++ source code' 1708f92157deSopenharmony_ci filename: 'file1' 1709f92157deSopenharmony_ci 1710f92157deSopenharmony_ci Returns: 1711f92157deSopenharmony_ci AstBuilder 1712f92157deSopenharmony_ci """ 1713f92157deSopenharmony_ci return AstBuilder(tokenize.GetTokens(source), filename) 1714f92157deSopenharmony_ci 1715f92157deSopenharmony_ci 1716f92157deSopenharmony_cidef PrintIndentifiers(filename, should_print): 1717f92157deSopenharmony_ci """Prints all identifiers for a C++ source file. 1718f92157deSopenharmony_ci 1719f92157deSopenharmony_ci Args: 1720f92157deSopenharmony_ci filename: 'file1' 1721f92157deSopenharmony_ci should_print: predicate with signature: bool Function(token) 1722f92157deSopenharmony_ci """ 1723f92157deSopenharmony_ci source = utils.ReadFile(filename, False) 1724f92157deSopenharmony_ci if source is None: 1725f92157deSopenharmony_ci sys.stderr.write('Unable to find: %s\n' % filename) 1726f92157deSopenharmony_ci return 1727f92157deSopenharmony_ci 1728f92157deSopenharmony_ci #print('Processing %s' % actual_filename) 1729f92157deSopenharmony_ci builder = BuilderFromSource(source, filename) 1730f92157deSopenharmony_ci try: 1731f92157deSopenharmony_ci for node in builder.Generate(): 1732f92157deSopenharmony_ci if should_print(node): 1733f92157deSopenharmony_ci print(node.name) 1734f92157deSopenharmony_ci except KeyboardInterrupt: 1735f92157deSopenharmony_ci return 1736f92157deSopenharmony_ci except: 1737f92157deSopenharmony_ci pass 1738f92157deSopenharmony_ci 1739f92157deSopenharmony_ci 1740f92157deSopenharmony_cidef PrintAllIndentifiers(filenames, should_print): 1741f92157deSopenharmony_ci """Prints all identifiers for each C++ source file in filenames. 1742f92157deSopenharmony_ci 1743f92157deSopenharmony_ci Args: 1744f92157deSopenharmony_ci filenames: ['file1', 'file2', ...] 1745f92157deSopenharmony_ci should_print: predicate with signature: bool Function(token) 1746f92157deSopenharmony_ci """ 1747f92157deSopenharmony_ci for path in filenames: 1748f92157deSopenharmony_ci PrintIndentifiers(path, should_print) 1749f92157deSopenharmony_ci 1750f92157deSopenharmony_ci 1751f92157deSopenharmony_cidef main(argv): 1752f92157deSopenharmony_ci for filename in argv[1:]: 1753f92157deSopenharmony_ci source = utils.ReadFile(filename) 1754f92157deSopenharmony_ci if source is None: 1755f92157deSopenharmony_ci continue 1756f92157deSopenharmony_ci 1757f92157deSopenharmony_ci print('Processing %s' % filename) 1758f92157deSopenharmony_ci builder = BuilderFromSource(source, filename) 1759f92157deSopenharmony_ci try: 1760f92157deSopenharmony_ci entire_ast = filter(None, builder.Generate()) 1761f92157deSopenharmony_ci except KeyboardInterrupt: 1762f92157deSopenharmony_ci return 1763f92157deSopenharmony_ci except: 1764f92157deSopenharmony_ci # Already printed a warning, print the traceback and continue. 1765f92157deSopenharmony_ci traceback.print_exc() 1766f92157deSopenharmony_ci else: 1767f92157deSopenharmony_ci if utils.DEBUG: 1768f92157deSopenharmony_ci for ast in entire_ast: 1769f92157deSopenharmony_ci print(ast) 1770f92157deSopenharmony_ci 1771f92157deSopenharmony_ci 1772f92157deSopenharmony_ciif __name__ == '__main__': 1773f92157deSopenharmony_ci main(sys.argv) 1774