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