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