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