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