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


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:48