00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 """Generate an Abstract Syntax Tree (AST) for C++."""
00019
00020 __author__ = 'nnorwitz@google.com (Neal Norwitz)'
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 try:
00036
00037 import builtins
00038 except ImportError:
00039
00040 import __builtin__ as builtins
00041
00042 import sys
00043 import traceback
00044
00045 from cpp import keywords
00046 from cpp import tokenize
00047 from cpp import utils
00048
00049
00050 if not hasattr(builtins, 'reversed'):
00051
00052 def reversed(seq):
00053 for i in range(len(seq)-1, -1, -1):
00054 yield seq[i]
00055
00056 if not hasattr(builtins, 'next'):
00057
00058 def next(obj):
00059 return obj.next()
00060
00061
00062 VISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3)
00063
00064 FUNCTION_NONE = 0x00
00065 FUNCTION_CONST = 0x01
00066 FUNCTION_VIRTUAL = 0x02
00067 FUNCTION_PURE_VIRTUAL = 0x04
00068 FUNCTION_CTOR = 0x08
00069 FUNCTION_DTOR = 0x10
00070 FUNCTION_ATTRIBUTE = 0x20
00071 FUNCTION_UNKNOWN_ANNOTATION = 0x40
00072 FUNCTION_THROW = 0x80
00073
00074 """
00075 These are currently unused. Should really handle these properly at some point.
00076
00077 TYPE_MODIFIER_INLINE = 0x010000
00078 TYPE_MODIFIER_EXTERN = 0x020000
00079 TYPE_MODIFIER_STATIC = 0x040000
00080 TYPE_MODIFIER_CONST = 0x080000
00081 TYPE_MODIFIER_REGISTER = 0x100000
00082 TYPE_MODIFIER_VOLATILE = 0x200000
00083 TYPE_MODIFIER_MUTABLE = 0x400000
00084
00085 TYPE_MODIFIER_MAP = {
00086 'inline': TYPE_MODIFIER_INLINE,
00087 'extern': TYPE_MODIFIER_EXTERN,
00088 'static': TYPE_MODIFIER_STATIC,
00089 'const': TYPE_MODIFIER_CONST,
00090 'register': TYPE_MODIFIER_REGISTER,
00091 'volatile': TYPE_MODIFIER_VOLATILE,
00092 'mutable': TYPE_MODIFIER_MUTABLE,
00093 }
00094 """
00095
00096 _INTERNAL_TOKEN = 'internal'
00097 _NAMESPACE_POP = 'ns-pop'
00098
00099
00100
00101
00102 class _NullDict(object):
00103 __contains__ = lambda self: False
00104 keys = values = items = iterkeys = itervalues = iteritems = lambda self: ()
00105
00106
00107
00108 class Node(object):
00109 """Base AST node."""
00110
00111 def __init__(self, start, end):
00112 self.start = start
00113 self.end = end
00114
00115 def IsDeclaration(self):
00116 """Returns bool if this node is a declaration."""
00117 return False
00118
00119 def IsDefinition(self):
00120 """Returns bool if this node is a definition."""
00121 return False
00122
00123 def IsExportable(self):
00124 """Returns bool if this node exportable from a header file."""
00125 return False
00126
00127 def Requires(self, node):
00128 """Does this AST node require the definition of the node passed in?"""
00129 return False
00130
00131 def XXX__str__(self):
00132 return self._StringHelper(self.__class__.__name__, '')
00133
00134 def _StringHelper(self, name, suffix):
00135 if not utils.DEBUG:
00136 return '%s(%s)' % (name, suffix)
00137 return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix)
00138
00139 def __repr__(self):
00140 return str(self)
00141
00142
00143 class Define(Node):
00144 def __init__(self, start, end, name, definition):
00145 Node.__init__(self, start, end)
00146 self.name = name
00147 self.definition = definition
00148
00149 def __str__(self):
00150 value = '%s %s' % (self.name, self.definition)
00151 return self._StringHelper(self.__class__.__name__, value)
00152
00153
00154 class Include(Node):
00155 def __init__(self, start, end, filename, system):
00156 Node.__init__(self, start, end)
00157 self.filename = filename
00158 self.system = system
00159
00160 def __str__(self):
00161 fmt = '"%s"'
00162 if self.system:
00163 fmt = '<%s>'
00164 return self._StringHelper(self.__class__.__name__, fmt % self.filename)
00165
00166
00167 class Goto(Node):
00168 def __init__(self, start, end, label):
00169 Node.__init__(self, start, end)
00170 self.label = label
00171
00172 def __str__(self):
00173 return self._StringHelper(self.__class__.__name__, str(self.label))
00174
00175
00176 class Expr(Node):
00177 def __init__(self, start, end, expr):
00178 Node.__init__(self, start, end)
00179 self.expr = expr
00180
00181 def Requires(self, node):
00182
00183 return False
00184
00185 def __str__(self):
00186 return self._StringHelper(self.__class__.__name__, str(self.expr))
00187
00188
00189 class Return(Expr):
00190 pass
00191
00192
00193 class Delete(Expr):
00194 pass
00195
00196
00197 class Friend(Expr):
00198 def __init__(self, start, end, expr, namespace):
00199 Expr.__init__(self, start, end, expr)
00200 self.namespace = namespace[:]
00201
00202
00203 class Using(Node):
00204 def __init__(self, start, end, names):
00205 Node.__init__(self, start, end)
00206 self.names = names
00207
00208 def __str__(self):
00209 return self._StringHelper(self.__class__.__name__, str(self.names))
00210
00211
00212 class Parameter(Node):
00213 def __init__(self, start, end, name, parameter_type, default):
00214 Node.__init__(self, start, end)
00215 self.name = name
00216 self.type = parameter_type
00217 self.default = default
00218
00219 def Requires(self, node):
00220
00221 return self.type.name == node.name
00222
00223 def __str__(self):
00224 name = str(self.type)
00225 suffix = '%s %s' % (name, self.name)
00226 if self.default:
00227 suffix += ' = ' + ''.join([d.name for d in self.default])
00228 return self._StringHelper(self.__class__.__name__, suffix)
00229
00230
00231 class _GenericDeclaration(Node):
00232 def __init__(self, start, end, name, namespace):
00233 Node.__init__(self, start, end)
00234 self.name = name
00235 self.namespace = namespace[:]
00236
00237 def FullName(self):
00238 prefix = ''
00239 if self.namespace and self.namespace[-1]:
00240 prefix = '::'.join(self.namespace) + '::'
00241 return prefix + self.name
00242
00243 def _TypeStringHelper(self, suffix):
00244 if self.namespace:
00245 names = [n or '<anonymous>' for n in self.namespace]
00246 suffix += ' in ' + '::'.join(names)
00247 return self._StringHelper(self.__class__.__name__, suffix)
00248
00249
00250
00251 class VariableDeclaration(_GenericDeclaration):
00252 def __init__(self, start, end, name, var_type, initial_value, namespace):
00253 _GenericDeclaration.__init__(self, start, end, name, namespace)
00254 self.type = var_type
00255 self.initial_value = initial_value
00256
00257 def Requires(self, node):
00258
00259 return self.type.name == node.name
00260
00261 def ToString(self):
00262 """Return a string that tries to reconstitute the variable decl."""
00263 suffix = '%s %s' % (self.type, self.name)
00264 if self.initial_value:
00265 suffix += ' = ' + self.initial_value
00266 return suffix
00267
00268 def __str__(self):
00269 return self._StringHelper(self.__class__.__name__, self.ToString())
00270
00271
00272 class Typedef(_GenericDeclaration):
00273 def __init__(self, start, end, name, alias, namespace):
00274 _GenericDeclaration.__init__(self, start, end, name, namespace)
00275 self.alias = alias
00276
00277 def IsDefinition(self):
00278 return True
00279
00280 def IsExportable(self):
00281 return True
00282
00283 def Requires(self, node):
00284
00285 name = node.name
00286 for token in self.alias:
00287 if token is not None and name == token.name:
00288 return True
00289 return False
00290
00291 def __str__(self):
00292 suffix = '%s, %s' % (self.name, self.alias)
00293 return self._TypeStringHelper(suffix)
00294
00295
00296 class _NestedType(_GenericDeclaration):
00297 def __init__(self, start, end, name, fields, namespace):
00298 _GenericDeclaration.__init__(self, start, end, name, namespace)
00299 self.fields = fields
00300
00301 def IsDefinition(self):
00302 return True
00303
00304 def IsExportable(self):
00305 return True
00306
00307 def __str__(self):
00308 suffix = '%s, {%s}' % (self.name, self.fields)
00309 return self._TypeStringHelper(suffix)
00310
00311
00312 class Union(_NestedType):
00313 pass
00314
00315
00316 class Enum(_NestedType):
00317 pass
00318
00319
00320 class Class(_GenericDeclaration):
00321 def __init__(self, start, end, name, bases, templated_types, body, namespace):
00322 _GenericDeclaration.__init__(self, start, end, name, namespace)
00323 self.bases = bases
00324 self.body = body
00325 self.templated_types = templated_types
00326
00327 def IsDeclaration(self):
00328 return self.bases is None and self.body is None
00329
00330 def IsDefinition(self):
00331 return not self.IsDeclaration()
00332
00333 def IsExportable(self):
00334 return not self.IsDeclaration()
00335
00336 def Requires(self, node):
00337
00338 if self.bases:
00339 for token_list in self.bases:
00340
00341 for token in token_list:
00342 if token.name == node.name:
00343 return True
00344
00345 return False
00346
00347 def __str__(self):
00348 name = self.name
00349 if self.templated_types:
00350 name += '<%s>' % self.templated_types
00351 suffix = '%s, %s, %s' % (name, self.bases, self.body)
00352 return self._TypeStringHelper(suffix)
00353
00354
00355 class Struct(Class):
00356 pass
00357
00358
00359 class Function(_GenericDeclaration):
00360 def __init__(self, start, end, name, return_type, parameters,
00361 modifiers, templated_types, body, namespace):
00362 _GenericDeclaration.__init__(self, start, end, name, namespace)
00363 converter = TypeConverter(namespace)
00364 self.return_type = converter.CreateReturnType(return_type)
00365 self.parameters = converter.ToParameters(parameters)
00366 self.modifiers = modifiers
00367 self.body = body
00368 self.templated_types = templated_types
00369
00370 def IsDeclaration(self):
00371 return self.body is None
00372
00373 def IsDefinition(self):
00374 return self.body is not None
00375
00376 def IsExportable(self):
00377 if self.return_type and 'static' in self.return_type.modifiers:
00378 return False
00379 return None not in self.namespace
00380
00381 def Requires(self, node):
00382 if self.parameters:
00383
00384 for p in self.parameters:
00385 if p.name == node.name:
00386 return True
00387
00388 return False
00389
00390 def __str__(self):
00391
00392 suffix = ('%s %s(%s), 0x%02x, %s' %
00393 (self.return_type, self.name, self.parameters,
00394 self.modifiers, self.body))
00395 return self._TypeStringHelper(suffix)
00396
00397
00398 class Method(Function):
00399 def __init__(self, start, end, name, in_class, return_type, parameters,
00400 modifiers, templated_types, body, namespace):
00401 Function.__init__(self, start, end, name, return_type, parameters,
00402 modifiers, templated_types, body, namespace)
00403
00404
00405 self.in_class = in_class
00406
00407
00408 class Type(_GenericDeclaration):
00409 """Type used for any variable (eg class, primitive, struct, etc)."""
00410
00411 def __init__(self, start, end, name, templated_types, modifiers,
00412 reference, pointer, array):
00413 """
00414 Args:
00415 name: str name of main type
00416 templated_types: [Class (Type?)] template type info between <>
00417 modifiers: [str] type modifiers (keywords) eg, const, mutable, etc.
00418 reference, pointer, array: bools
00419 """
00420 _GenericDeclaration.__init__(self, start, end, name, [])
00421 self.templated_types = templated_types
00422 if not name and modifiers:
00423 self.name = modifiers.pop()
00424 self.modifiers = modifiers
00425 self.reference = reference
00426 self.pointer = pointer
00427 self.array = array
00428
00429 def __str__(self):
00430 prefix = ''
00431 if self.modifiers:
00432 prefix = ' '.join(self.modifiers) + ' '
00433 name = str(self.name)
00434 if self.templated_types:
00435 name += '<%s>' % self.templated_types
00436 suffix = prefix + name
00437 if self.reference:
00438 suffix += '&'
00439 if self.pointer:
00440 suffix += '*'
00441 if self.array:
00442 suffix += '[]'
00443 return self._TypeStringHelper(suffix)
00444
00445
00446
00447 def IsDeclaration(self):
00448 return False
00449
00450 def IsDefinition(self):
00451 return False
00452
00453 def IsExportable(self):
00454 return False
00455
00456
00457 class TypeConverter(object):
00458
00459 def __init__(self, namespace_stack):
00460 self.namespace_stack = namespace_stack
00461
00462 def _GetTemplateEnd(self, tokens, start):
00463 count = 1
00464 end = start
00465 while 1:
00466 token = tokens[end]
00467 end += 1
00468 if token.name == '<':
00469 count += 1
00470 elif token.name == '>':
00471 count -= 1
00472 if count == 0:
00473 break
00474 return tokens[start:end-1], end
00475
00476 def ToType(self, tokens):
00477 """Convert [Token,...] to [Class(...), ] useful for base classes.
00478 For example, code like class Foo : public Bar<x, y> { ... };
00479 the "Bar<x, y>" portion gets converted to an AST.
00480
00481 Returns:
00482 [Class(...), ...]
00483 """
00484 result = []
00485 name_tokens = []
00486 reference = pointer = array = False
00487
00488 def AddType(templated_types):
00489
00490 names = []
00491 modifiers = []
00492 for t in name_tokens:
00493 if keywords.IsKeyword(t.name):
00494 modifiers.append(t.name)
00495 else:
00496 names.append(t.name)
00497 name = ''.join(names)
00498 result.append(Type(name_tokens[0].start, name_tokens[-1].end,
00499 name, templated_types, modifiers,
00500 reference, pointer, array))
00501 del name_tokens[:]
00502
00503 i = 0
00504 end = len(tokens)
00505 while i < end:
00506 token = tokens[i]
00507 if token.name == '<':
00508 new_tokens, new_end = self._GetTemplateEnd(tokens, i+1)
00509 AddType(self.ToType(new_tokens))
00510
00511
00512 i = new_end
00513 reference = pointer = array = False
00514 elif token.name == ',':
00515 AddType([])
00516 reference = pointer = array = False
00517 elif token.name == '*':
00518 pointer = True
00519 elif token.name == '&':
00520 reference = True
00521 elif token.name == '[':
00522 pointer = True
00523 elif token.name == ']':
00524 pass
00525 else:
00526 name_tokens.append(token)
00527 i += 1
00528
00529 if name_tokens:
00530
00531 AddType([])
00532 return result
00533
00534 def DeclarationToParts(self, parts, needs_name_removed):
00535 name = None
00536 default = []
00537 if needs_name_removed:
00538
00539 for i, t in enumerate(parts):
00540 if t.name == '=':
00541 default = parts[i+1:]
00542 name = parts[i-1].name
00543 if name == ']' and parts[i-2].name == '[':
00544 name = parts[i-3].name
00545 i -= 1
00546 parts = parts[:i-1]
00547 break
00548 else:
00549 if parts[-1].token_type == tokenize.NAME:
00550 name = parts.pop().name
00551 else:
00552
00553
00554
00555 name = '???'
00556 modifiers = []
00557 type_name = []
00558 other_tokens = []
00559 templated_types = []
00560 i = 0
00561 end = len(parts)
00562 while i < end:
00563 p = parts[i]
00564 if keywords.IsKeyword(p.name):
00565 modifiers.append(p.name)
00566 elif p.name == '<':
00567 templated_tokens, new_end = self._GetTemplateEnd(parts, i+1)
00568 templated_types = self.ToType(templated_tokens)
00569 i = new_end - 1
00570
00571 next_index = i + 1
00572 if next_index < end and parts[next_index].name == '::':
00573 i += 1
00574 elif p.name in ('[', ']', '='):
00575
00576 other_tokens.append(p)
00577 elif p.name not in ('*', '&', '>'):
00578
00579 if (type_name and type_name[-1].token_type == tokenize.NAME and
00580 p.token_type == tokenize.NAME):
00581 type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0))
00582 type_name.append(p)
00583 else:
00584 other_tokens.append(p)
00585 i += 1
00586 type_name = ''.join([t.name for t in type_name])
00587 return name, type_name, templated_types, modifiers, default, other_tokens
00588
00589 def ToParameters(self, tokens):
00590 if not tokens:
00591 return []
00592
00593 result = []
00594 name = type_name = ''
00595 type_modifiers = []
00596 pointer = reference = array = False
00597 first_token = None
00598 default = []
00599
00600 def AddParameter():
00601 if default:
00602 del default[0]
00603 end = type_modifiers[-1].end
00604 parts = self.DeclarationToParts(type_modifiers, True)
00605 (name, type_name, templated_types, modifiers,
00606 unused_default, unused_other_tokens) = parts
00607 parameter_type = Type(first_token.start, first_token.end,
00608 type_name, templated_types, modifiers,
00609 reference, pointer, array)
00610 p = Parameter(first_token.start, end, name,
00611 parameter_type, default)
00612 result.append(p)
00613
00614 template_count = 0
00615 for s in tokens:
00616 if not first_token:
00617 first_token = s
00618 if s.name == '<':
00619 template_count += 1
00620 elif s.name == '>':
00621 template_count -= 1
00622 if template_count > 0:
00623 type_modifiers.append(s)
00624 continue
00625
00626 if s.name == ',':
00627 AddParameter()
00628 name = type_name = ''
00629 type_modifiers = []
00630 pointer = reference = array = False
00631 first_token = None
00632 default = []
00633 elif s.name == '*':
00634 pointer = True
00635 elif s.name == '&':
00636 reference = True
00637 elif s.name == '[':
00638 array = True
00639 elif s.name == ']':
00640 pass
00641 elif s.name == '=':
00642
00643 default.append(None)
00644 elif default:
00645 default.append(s)
00646 else:
00647 type_modifiers.append(s)
00648 AddParameter()
00649 return result
00650
00651 def CreateReturnType(self, return_type_seq):
00652 if not return_type_seq:
00653 return None
00654 start = return_type_seq[0].start
00655 end = return_type_seq[-1].end
00656 _, name, templated_types, modifiers, default, other_tokens = \
00657 self.DeclarationToParts(return_type_seq, False)
00658 names = [n.name for n in other_tokens]
00659 reference = '&' in names
00660 pointer = '*' in names
00661 array = '[' in names
00662 return Type(start, end, name, templated_types, modifiers,
00663 reference, pointer, array)
00664
00665 def GetTemplateIndices(self, names):
00666
00667 start = names.index('<')
00668 end = len(names) - 1
00669 while end > 0:
00670 if names[end] == '>':
00671 break
00672 end -= 1
00673 return start, end+1
00674
00675 class AstBuilder(object):
00676 def __init__(self, token_stream, filename, in_class='', visibility=None,
00677 namespace_stack=[]):
00678 self.tokens = token_stream
00679 self.filename = filename
00680
00681
00682
00683 self.token_queue = []
00684 self.namespace_stack = namespace_stack[:]
00685 self.in_class = in_class
00686 if in_class is None:
00687 self.in_class_name_only = None
00688 else:
00689 self.in_class_name_only = in_class.split('::')[-1]
00690 self.visibility = visibility
00691 self.in_function = False
00692 self.current_token = None
00693
00694 self._handling_typedef = False
00695
00696 self.converter = TypeConverter(self.namespace_stack)
00697
00698 def HandleError(self, msg, token):
00699 printable_queue = list(reversed(self.token_queue[-20:]))
00700 sys.stderr.write('Got %s in %s @ %s %s\n' %
00701 (msg, self.filename, token, printable_queue))
00702
00703 def Generate(self):
00704 while 1:
00705 token = self._GetNextToken()
00706 if not token:
00707 break
00708
00709
00710 self.current_token = token
00711
00712
00713 if token.token_type == _INTERNAL_TOKEN:
00714 if token.name == _NAMESPACE_POP:
00715 self.namespace_stack.pop()
00716 continue
00717
00718 try:
00719 result = self._GenerateOne(token)
00720 if result is not None:
00721 yield result
00722 except:
00723 self.HandleError('exception', token)
00724 raise
00725
00726 def _CreateVariable(self, pos_token, name, type_name, type_modifiers,
00727 ref_pointer_name_seq, templated_types, value=None):
00728 reference = '&' in ref_pointer_name_seq
00729 pointer = '*' in ref_pointer_name_seq
00730 array = '[' in ref_pointer_name_seq
00731 var_type = Type(pos_token.start, pos_token.end, type_name,
00732 templated_types, type_modifiers,
00733 reference, pointer, array)
00734 return VariableDeclaration(pos_token.start, pos_token.end,
00735 name, var_type, value, self.namespace_stack)
00736
00737 def _GenerateOne(self, token):
00738 if token.token_type == tokenize.NAME:
00739 if (keywords.IsKeyword(token.name) and
00740 not keywords.IsBuiltinType(token.name)):
00741 method = getattr(self, 'handle_' + token.name)
00742 return method()
00743 elif token.name == self.in_class_name_only:
00744
00745
00746
00747 next = self._GetNextToken()
00748 self._AddBackToken(next)
00749 if next.token_type == tokenize.SYNTAX and next.name == '(':
00750 return self._GetMethod([token], FUNCTION_CTOR, None, True)
00751
00752
00753
00754 syntax = tokenize.SYNTAX
00755 temp_tokens, last_token = \
00756 self._GetVarTokensUpTo(syntax, '(', ';', '{', '[')
00757 temp_tokens.insert(0, token)
00758 if last_token.name == '(':
00759
00760
00761 expr = bool([e for e in temp_tokens if e.name == '='])
00762 if expr:
00763 new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';')
00764 temp_tokens.append(last_token)
00765 temp_tokens.extend(new_temp)
00766 last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0)
00767
00768 if last_token.name == '[':
00769
00770
00771
00772 temp_tokens.append(last_token)
00773 if temp_tokens[-2].name == 'operator':
00774 temp_tokens.append(self._GetNextToken())
00775 else:
00776 temp_tokens2, last_token = \
00777 self._GetVarTokensUpTo(tokenize.SYNTAX, ';')
00778 temp_tokens.extend(temp_tokens2)
00779
00780 if last_token.name == ';':
00781
00782 parts = self.converter.DeclarationToParts(temp_tokens, True)
00783 (name, type_name, templated_types, modifiers, default,
00784 unused_other_tokens) = parts
00785
00786 t0 = temp_tokens[0]
00787 names = [t.name for t in temp_tokens]
00788 if templated_types:
00789 start, end = self.converter.GetTemplateIndices(names)
00790 names = names[:start] + names[end:]
00791 default = ''.join([t.name for t in default])
00792 return self._CreateVariable(t0, name, type_name, modifiers,
00793 names, templated_types, default)
00794 if last_token.name == '{':
00795 self._AddBackTokens(temp_tokens[1:])
00796 self._AddBackToken(last_token)
00797 method_name = temp_tokens[0].name
00798 method = getattr(self, 'handle_' + method_name, None)
00799 if not method:
00800
00801
00802 return None
00803 return method()
00804 return self._GetMethod(temp_tokens, 0, None, False)
00805 elif token.token_type == tokenize.SYNTAX:
00806 if token.name == '~' and self.in_class:
00807
00808 token = self._GetNextToken()
00809
00810
00811 if (token.token_type == tokenize.NAME and
00812 token.name == self.in_class_name_only):
00813 return self._GetMethod([token], FUNCTION_DTOR, None, True)
00814
00815 elif token.token_type == tokenize.PREPROCESSOR:
00816
00817
00818 name = token.name[1:].lstrip()
00819 if name.startswith('include'):
00820
00821 name = name[7:].strip()
00822 assert name
00823
00824 if name.startswith('\\'):
00825 name = name[1:].strip()
00826 assert name[0] in '<"', token
00827 assert name[-1] in '>"', token
00828 system = name[0] == '<'
00829 filename = name[1:-1]
00830 return Include(token.start, token.end, filename, system)
00831 if name.startswith('define'):
00832
00833 name = name[6:].strip()
00834 assert name
00835 value = ''
00836 for i, c in enumerate(name):
00837 if c.isspace():
00838 value = name[i:].lstrip()
00839 name = name[:i]
00840 break
00841 return Define(token.start, token.end, name, value)
00842 if name.startswith('if') and name[2:3].isspace():
00843 condition = name[3:].strip()
00844 if condition.startswith('0') or condition.startswith('(0)'):
00845 self._SkipIf0Blocks()
00846 return None
00847
00848 def _GetTokensUpTo(self, expected_token_type, expected_token):
00849 return self._GetVarTokensUpTo(expected_token_type, expected_token)[0]
00850
00851 def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens):
00852 last_token = self._GetNextToken()
00853 tokens = []
00854 while (last_token.token_type != expected_token_type or
00855 last_token.name not in expected_tokens):
00856 tokens.append(last_token)
00857 last_token = self._GetNextToken()
00858 return tokens, last_token
00859
00860
00861 def _IgnoreUpTo(self, token_type, token):
00862 unused_tokens = self._GetTokensUpTo(token_type, token)
00863
00864 def _SkipIf0Blocks(self):
00865 count = 1
00866 while 1:
00867 token = self._GetNextToken()
00868 if token.token_type != tokenize.PREPROCESSOR:
00869 continue
00870
00871 name = token.name[1:].lstrip()
00872 if name.startswith('endif'):
00873 count -= 1
00874 if count == 0:
00875 break
00876 elif name.startswith('if'):
00877 count += 1
00878
00879 def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None):
00880 if GetNextToken is None:
00881 GetNextToken = self._GetNextToken
00882
00883
00884 count = 1
00885 token = GetNextToken()
00886 while 1:
00887 if token.token_type == tokenize.SYNTAX:
00888 if token.name == open_paren:
00889 count += 1
00890 elif token.name == close_paren:
00891 count -= 1
00892 if count == 0:
00893 break
00894 yield token
00895 token = GetNextToken()
00896 yield token
00897
00898 def _GetParameters(self):
00899 return self._GetMatchingChar('(', ')')
00900
00901 def GetScope(self):
00902 return self._GetMatchingChar('{', '}')
00903
00904 def _GetNextToken(self):
00905 if self.token_queue:
00906 return self.token_queue.pop()
00907 return next(self.tokens)
00908
00909 def _AddBackToken(self, token):
00910 if token.whence == tokenize.WHENCE_STREAM:
00911 token.whence = tokenize.WHENCE_QUEUE
00912 self.token_queue.insert(0, token)
00913 else:
00914 assert token.whence == tokenize.WHENCE_QUEUE, token
00915 self.token_queue.append(token)
00916
00917 def _AddBackTokens(self, tokens):
00918 if tokens:
00919 if tokens[-1].whence == tokenize.WHENCE_STREAM:
00920 for token in tokens:
00921 token.whence = tokenize.WHENCE_QUEUE
00922 self.token_queue[:0] = reversed(tokens)
00923 else:
00924 assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens
00925 self.token_queue.extend(reversed(tokens))
00926
00927 def GetName(self, seq=None):
00928 """Returns ([tokens], next_token_info)."""
00929 GetNextToken = self._GetNextToken
00930 if seq is not None:
00931 it = iter(seq)
00932 GetNextToken = lambda: next(it)
00933 next_token = GetNextToken()
00934 tokens = []
00935 last_token_was_name = False
00936 while (next_token.token_type == tokenize.NAME or
00937 (next_token.token_type == tokenize.SYNTAX and
00938 next_token.name in ('::', '<'))):
00939
00940
00941 if last_token_was_name and next_token.token_type == tokenize.NAME:
00942 break
00943 last_token_was_name = next_token.token_type == tokenize.NAME
00944 tokens.append(next_token)
00945
00946 if next_token.name == '<':
00947 tokens.extend(self._GetMatchingChar('<', '>', GetNextToken))
00948 last_token_was_name = True
00949 next_token = GetNextToken()
00950 return tokens, next_token
00951
00952 def GetMethod(self, modifiers, templated_types):
00953 return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')
00954 assert len(return_type_and_name) >= 1
00955 return self._GetMethod(return_type_and_name, modifiers, templated_types,
00956 False)
00957
00958 def _GetMethod(self, return_type_and_name, modifiers, templated_types,
00959 get_paren):
00960 template_portion = None
00961 if get_paren:
00962 token = self._GetNextToken()
00963 assert token.token_type == tokenize.SYNTAX, token
00964 if token.name == '<':
00965
00966 template_portion = [token]
00967 template_portion.extend(self._GetMatchingChar('<', '>'))
00968 token = self._GetNextToken()
00969 assert token.token_type == tokenize.SYNTAX, token
00970 assert token.name == '(', token
00971
00972 name = return_type_and_name.pop()
00973
00974 if name.name == '>':
00975 index = 1
00976 while return_type_and_name[index].name != '<':
00977 index += 1
00978 template_portion = return_type_and_name[index:] + [name]
00979 del return_type_and_name[index:]
00980 name = return_type_and_name.pop()
00981 elif name.name == ']':
00982 rt = return_type_and_name
00983 assert rt[-1].name == '[', return_type_and_name
00984 assert rt[-2].name == 'operator', return_type_and_name
00985 name_seq = return_type_and_name[-2:]
00986 del return_type_and_name[-2:]
00987 name = tokenize.Token(tokenize.NAME, 'operator[]',
00988 name_seq[0].start, name.end)
00989
00990 unused_open_paren = self._GetNextToken()
00991
00992
00993 return_type = return_type_and_name
00994 indices = name
00995 if return_type:
00996 indices = return_type[0]
00997
00998
00999 if name.name == self.in_class and not modifiers:
01000 modifiers |= FUNCTION_CTOR
01001 parameters = list(self._GetParameters())
01002 del parameters[-1]
01003
01004
01005 if name.name == 'operator' and not parameters:
01006 token = self._GetNextToken()
01007 assert token.name == '(', token
01008 parameters = list(self._GetParameters())
01009 del parameters[-1]
01010
01011 token = self._GetNextToken()
01012 while token.token_type == tokenize.NAME:
01013 modifier_token = token
01014 token = self._GetNextToken()
01015 if modifier_token.name == 'const':
01016 modifiers |= FUNCTION_CONST
01017 elif modifier_token.name == '__attribute__':
01018
01019 modifiers |= FUNCTION_ATTRIBUTE
01020 assert token.name == '(', token
01021
01022 unused_tokens = list(self._GetMatchingChar('(', ')'))
01023 token = self._GetNextToken()
01024 elif modifier_token.name == 'throw':
01025 modifiers |= FUNCTION_THROW
01026 assert token.name == '(', token
01027
01028 unused_tokens = list(self._GetMatchingChar('(', ')'))
01029 token = self._GetNextToken()
01030 elif modifier_token.name == modifier_token.name.upper():
01031
01032
01033 modifiers |= FUNCTION_UNKNOWN_ANNOTATION
01034 else:
01035 self.HandleError('unexpected token', modifier_token)
01036
01037 assert token.token_type == tokenize.SYNTAX, token
01038
01039 if token.name == ':':
01040
01041 while token.name != ';' and token.name != '{':
01042 token = self._GetNextToken()
01043
01044
01045
01046 if token.name == '(':
01047 if parameters[0].name == '*':
01048
01049 name = parameters.pop()
01050
01051 modifiers = [p.name for p in parameters]
01052
01053 function_parameters = list(self._GetMatchingChar('(', ')'))
01054 del function_parameters[-1]
01055
01056 token = self._GetNextToken()
01057 assert token.token_type == tokenize.SYNTAX, token
01058 assert token.name == ';', token
01059 return self._CreateVariable(indices, name.name, indices.name,
01060 modifiers, '', None)
01061
01062
01063
01064
01065
01066
01067
01068
01069 real_name = parameters[-1]
01070 modifiers = [p.name for p in self._GetParameters()]
01071 del modifiers[-1]
01072 return self._CreateVariable(indices, real_name.name, indices.name,
01073 modifiers, '', None)
01074
01075 if token.name == '{':
01076 body = list(self.GetScope())
01077 del body[-1]
01078 else:
01079 body = None
01080 if token.name == '=':
01081 token = self._GetNextToken()
01082 assert token.token_type == tokenize.CONSTANT, token
01083 assert token.name == '0', token
01084 modifiers |= FUNCTION_PURE_VIRTUAL
01085 token = self._GetNextToken()
01086
01087 if token.name == '[':
01088
01089
01090 tokens = list(self._GetMatchingChar('[', ']'))
01091 token = self._GetNextToken()
01092
01093 assert token.name == ';', (token, return_type_and_name, parameters)
01094
01095
01096 if len(return_type) > 2 and return_type[-1].name == '::':
01097 return_type, in_class = \
01098 self._GetReturnTypeAndClassName(return_type)
01099 return Method(indices.start, indices.end, name.name, in_class,
01100 return_type, parameters, modifiers, templated_types,
01101 body, self.namespace_stack)
01102 return Function(indices.start, indices.end, name.name, return_type,
01103 parameters, modifiers, templated_types, body,
01104 self.namespace_stack)
01105
01106 def _GetReturnTypeAndClassName(self, token_seq):
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 i = 0
01117 if token_seq[0].name == '::':
01118 i = 1
01119
01120 end = len(token_seq) - 1
01121 if token_seq[end-1].name == '::':
01122 end -= 1
01123
01124
01125
01126
01127 seq_copy = token_seq[i:end]
01128 seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0))
01129 names = []
01130 while i < end:
01131
01132 new_name, next = self.GetName(seq_copy[i:])
01133 assert new_name, 'Got empty new_name, next=%s' % next
01134
01135 if next and next.token_type == tokenize.SYNTAX:
01136 new_name.append(next)
01137 names.append(new_name)
01138 i += len(new_name)
01139
01140
01141
01142
01143 names[-1].pop()
01144
01145 return_type = [e for seq in names[:-1] for e in seq]
01146
01147 class_name = names[-1]
01148 return return_type, class_name
01149
01150 def handle_bool(self):
01151 pass
01152
01153 def handle_char(self):
01154 pass
01155
01156 def handle_int(self):
01157 pass
01158
01159 def handle_long(self):
01160 pass
01161
01162 def handle_short(self):
01163 pass
01164
01165 def handle_double(self):
01166 pass
01167
01168 def handle_float(self):
01169 pass
01170
01171 def handle_void(self):
01172 pass
01173
01174 def handle_wchar_t(self):
01175 pass
01176
01177 def handle_unsigned(self):
01178 pass
01179
01180 def handle_signed(self):
01181 pass
01182
01183 def _GetNestedType(self, ctor):
01184 name = None
01185 name_tokens, token = self.GetName()
01186 if name_tokens:
01187 name = ''.join([t.name for t in name_tokens])
01188
01189
01190 if token.token_type == tokenize.SYNTAX and token.name == ';':
01191 return ctor(token.start, token.end, name, None,
01192 self.namespace_stack)
01193
01194 if token.token_type == tokenize.NAME and self._handling_typedef:
01195 self._AddBackToken(token)
01196 return ctor(token.start, token.end, name, None,
01197 self.namespace_stack)
01198
01199
01200 fields = list(self._GetMatchingChar('{', '}'))
01201 del fields[-1]
01202 if token.token_type == tokenize.SYNTAX and token.name == '{':
01203 next = self._GetNextToken()
01204 new_type = ctor(token.start, token.end, name, fields,
01205 self.namespace_stack)
01206
01207
01208 if next.token_type != tokenize.NAME:
01209 return new_type
01210 name = new_type
01211 token = next
01212
01213
01214 assert token.token_type == tokenize.NAME, token
01215 return self._CreateVariable(token, token.name, name, [], '', None)
01216
01217 def handle_struct(self):
01218
01219
01220 name_tokens, var_token = self.GetName()
01221 if name_tokens:
01222 next_token = self._GetNextToken()
01223 is_syntax = (var_token.token_type == tokenize.SYNTAX and
01224 var_token.name[0] in '*&')
01225 is_variable = (var_token.token_type == tokenize.NAME and
01226 next_token.name == ';')
01227 variable = var_token
01228 if is_syntax and not is_variable:
01229 variable = next_token
01230 temp = self._GetNextToken()
01231 if temp.token_type == tokenize.SYNTAX and temp.name == '(':
01232
01233 t0 = name_tokens[0]
01234 struct = tokenize.Token(tokenize.NAME, 'struct',
01235 t0.start-7, t0.start-2)
01236 type_and_name = [struct]
01237 type_and_name.extend(name_tokens)
01238 type_and_name.extend((var_token, next_token))
01239 return self._GetMethod(type_and_name, 0, None, False)
01240 assert temp.name == ';', (temp, name_tokens, var_token)
01241 if is_syntax or (is_variable and not self._handling_typedef):
01242 modifiers = ['struct']
01243 type_name = ''.join([t.name for t in name_tokens])
01244 position = name_tokens[0]
01245 return self._CreateVariable(position, variable.name, type_name,
01246 modifiers, var_token.name, None)
01247 name_tokens.extend((var_token, next_token))
01248 self._AddBackTokens(name_tokens)
01249 else:
01250 self._AddBackToken(var_token)
01251 return self._GetClass(Struct, VISIBILITY_PUBLIC, None)
01252
01253 def handle_union(self):
01254 return self._GetNestedType(Union)
01255
01256 def handle_enum(self):
01257 return self._GetNestedType(Enum)
01258
01259 def handle_auto(self):
01260
01261
01262 pass
01263
01264 def handle_register(self):
01265 pass
01266
01267 def handle_const(self):
01268 pass
01269
01270 def handle_inline(self):
01271 pass
01272
01273 def handle_extern(self):
01274 pass
01275
01276 def handle_static(self):
01277 pass
01278
01279 def handle_virtual(self):
01280
01281 token = token2 = self._GetNextToken()
01282 if token.name == 'inline':
01283
01284 token2 = self._GetNextToken()
01285 if token2.token_type == tokenize.SYNTAX and token2.name == '~':
01286 return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None)
01287 assert token.token_type == tokenize.NAME or token.name == '::', token
01288 return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(')
01289 return_type_and_name.insert(0, token)
01290 if token2 is not token:
01291 return_type_and_name.insert(1, token2)
01292 return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL,
01293 None, False)
01294
01295 def handle_volatile(self):
01296 pass
01297
01298 def handle_mutable(self):
01299 pass
01300
01301 def handle_public(self):
01302 assert self.in_class
01303 self.visibility = VISIBILITY_PUBLIC
01304
01305 def handle_protected(self):
01306 assert self.in_class
01307 self.visibility = VISIBILITY_PROTECTED
01308
01309 def handle_private(self):
01310 assert self.in_class
01311 self.visibility = VISIBILITY_PRIVATE
01312
01313 def handle_friend(self):
01314 tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
01315 assert tokens
01316 t0 = tokens[0]
01317 return Friend(t0.start, t0.end, tokens, self.namespace_stack)
01318
01319 def handle_static_cast(self):
01320 pass
01321
01322 def handle_const_cast(self):
01323 pass
01324
01325 def handle_dynamic_cast(self):
01326 pass
01327
01328 def handle_reinterpret_cast(self):
01329 pass
01330
01331 def handle_new(self):
01332 pass
01333
01334 def handle_delete(self):
01335 tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
01336 assert tokens
01337 return Delete(tokens[0].start, tokens[0].end, tokens)
01338
01339 def handle_typedef(self):
01340 token = self._GetNextToken()
01341 if (token.token_type == tokenize.NAME and
01342 keywords.IsKeyword(token.name)):
01343
01344 method = getattr(self, 'handle_' + token.name)
01345 self._handling_typedef = True
01346 tokens = [method()]
01347 self._handling_typedef = False
01348 else:
01349 tokens = [token]
01350
01351
01352 tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';'))
01353
01354
01355 assert tokens
01356 name = tokens.pop()
01357 indices = name
01358 if tokens:
01359 indices = tokens[0]
01360 if not indices:
01361 indices = token
01362 if name.name == ')':
01363
01364 if (len(tokens) >= 4 and
01365 tokens[1].name == '(' and tokens[2].name == '*'):
01366 tokens.append(name)
01367 name = tokens[3]
01368 elif name.name == ']':
01369
01370 if len(tokens) >= 2:
01371 tokens.append(name)
01372 name = tokens[1]
01373 new_type = tokens
01374 if tokens and isinstance(tokens[0], tokenize.Token):
01375 new_type = self.converter.ToType(tokens)[0]
01376 return Typedef(indices.start, indices.end, name.name,
01377 new_type, self.namespace_stack)
01378
01379 def handle_typeid(self):
01380 pass
01381
01382 def handle_typename(self):
01383 pass
01384
01385 def _GetTemplatedTypes(self):
01386 result = {}
01387 tokens = list(self._GetMatchingChar('<', '>'))
01388 len_tokens = len(tokens) - 1
01389 i = 0
01390 while i < len_tokens:
01391 key = tokens[i].name
01392 i += 1
01393 if keywords.IsKeyword(key) or key == ',':
01394 continue
01395 type_name = default = None
01396 if i < len_tokens:
01397 i += 1
01398 if tokens[i-1].name == '=':
01399 assert i < len_tokens, '%s %s' % (i, tokens)
01400 default, unused_next_token = self.GetName(tokens[i:])
01401 i += len(default)
01402 else:
01403 if tokens[i-1].name != ',':
01404
01405
01406 key = tokens[i-1].name
01407 type_name = tokens[i-2]
01408
01409 result[key] = (type_name, default)
01410 return result
01411
01412 def handle_template(self):
01413 token = self._GetNextToken()
01414 assert token.token_type == tokenize.SYNTAX, token
01415 assert token.name == '<', token
01416 templated_types = self._GetTemplatedTypes()
01417
01418 token = self._GetNextToken()
01419 if token.token_type == tokenize.NAME:
01420 if token.name == 'class':
01421 return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types)
01422 elif token.name == 'struct':
01423 return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types)
01424 elif token.name == 'friend':
01425 return self.handle_friend()
01426 self._AddBackToken(token)
01427 tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';')
01428 tokens.append(last)
01429 self._AddBackTokens(tokens)
01430 if last.name == '(':
01431 return self.GetMethod(FUNCTION_NONE, templated_types)
01432
01433 return None
01434
01435 def handle_true(self):
01436 pass
01437
01438 def handle_false(self):
01439 pass
01440
01441 def handle_asm(self):
01442 pass
01443
01444 def handle_class(self):
01445 return self._GetClass(Class, VISIBILITY_PRIVATE, None)
01446
01447 def _GetBases(self):
01448
01449 bases = []
01450 while 1:
01451 token = self._GetNextToken()
01452 assert token.token_type == tokenize.NAME, token
01453
01454 if token.name not in ('public', 'protected', 'private'):
01455
01456
01457
01458 self._AddBackToken(token)
01459 else:
01460
01461 token = self._GetNextToken()
01462 if token.name != 'virtual':
01463 self._AddBackToken(token)
01464 else:
01465
01466 pass
01467 base, next_token = self.GetName()
01468 bases_ast = self.converter.ToType(base)
01469 assert len(bases_ast) == 1, bases_ast
01470 bases.append(bases_ast[0])
01471 assert next_token.token_type == tokenize.SYNTAX, next_token
01472 if next_token.name == '{':
01473 token = next_token
01474 break
01475
01476 assert next_token.name == ',', next_token
01477 return bases, token
01478
01479 def _GetClass(self, class_type, visibility, templated_types):
01480 class_name = None
01481 class_token = self._GetNextToken()
01482 if class_token.token_type != tokenize.NAME:
01483 assert class_token.token_type == tokenize.SYNTAX, class_token
01484 token = class_token
01485 else:
01486
01487
01488 next_token = self._GetNextToken()
01489 if next_token.token_type == tokenize.NAME:
01490 self._AddBackToken(next_token)
01491 else:
01492 self._AddBackTokens([class_token, next_token])
01493 name_tokens, token = self.GetName()
01494 class_name = ''.join([t.name for t in name_tokens])
01495 bases = None
01496 if token.token_type == tokenize.SYNTAX:
01497 if token.name == ';':
01498
01499 return class_type(class_token.start, class_token.end,
01500 class_name, None, templated_types, None,
01501 self.namespace_stack)
01502 if token.name in '*&':
01503
01504 name_token = self._GetNextToken()
01505 next_token = self._GetNextToken()
01506 if next_token.name == ';':
01507
01508 modifiers = ['class']
01509 return self._CreateVariable(class_token, name_token.name,
01510 class_name,
01511 modifiers, token.name, None)
01512 else:
01513
01514 tokens = (class_token, token, name_token, next_token)
01515 self._AddBackTokens(tokens)
01516 return self.GetMethod(FUNCTION_NONE, None)
01517 if token.name == ':':
01518 bases, token = self._GetBases()
01519
01520 body = None
01521 if token.token_type == tokenize.SYNTAX and token.name == '{':
01522 assert token.token_type == tokenize.SYNTAX, token
01523 assert token.name == '{', token
01524
01525 ast = AstBuilder(self.GetScope(), self.filename, class_name,
01526 visibility, self.namespace_stack)
01527 body = list(ast.Generate())
01528
01529 if not self._handling_typedef:
01530 token = self._GetNextToken()
01531 if token.token_type != tokenize.NAME:
01532 assert token.token_type == tokenize.SYNTAX, token
01533 assert token.name == ';', token
01534 else:
01535 new_class = class_type(class_token.start, class_token.end,
01536 class_name, bases, None,
01537 body, self.namespace_stack)
01538
01539 modifiers = []
01540 return self._CreateVariable(class_token,
01541 token.name, new_class,
01542 modifiers, token.name, None)
01543 else:
01544 if not self._handling_typedef:
01545 self.HandleError('non-typedef token', token)
01546 self._AddBackToken(token)
01547
01548 return class_type(class_token.start, class_token.end, class_name,
01549 bases, templated_types, body, self.namespace_stack)
01550
01551 def handle_namespace(self):
01552 token = self._GetNextToken()
01553
01554 name = None
01555 if token.token_type == tokenize.NAME:
01556 name = token.name
01557 token = self._GetNextToken()
01558 self.namespace_stack.append(name)
01559 assert token.token_type == tokenize.SYNTAX, token
01560
01561 internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP,
01562 None, None)
01563 internal_token.whence = token.whence
01564 if token.name == '=':
01565
01566 name, next_token = self.GetName()
01567 assert next_token.name == ';', next_token
01568 self._AddBackToken(internal_token)
01569 else:
01570 assert token.name == '{', token
01571 tokens = list(self.GetScope())
01572
01573 tokens[-1] = internal_token
01574
01575 self._AddBackTokens(tokens)
01576 return None
01577
01578 def handle_using(self):
01579 tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
01580 assert tokens
01581 return Using(tokens[0].start, tokens[0].end, tokens)
01582
01583 def handle_explicit(self):
01584 assert self.in_class
01585
01586
01587
01588 return self.GetMethod(FUNCTION_CTOR, None)
01589
01590 def handle_this(self):
01591 pass
01592
01593 def handle_operator(self):
01594
01595 pass
01596
01597 def handle_sizeof(self):
01598 pass
01599
01600 def handle_case(self):
01601 pass
01602
01603 def handle_switch(self):
01604 pass
01605
01606 def handle_default(self):
01607 token = self._GetNextToken()
01608 assert token.token_type == tokenize.SYNTAX
01609 assert token.name == ':'
01610
01611 def handle_if(self):
01612 pass
01613
01614 def handle_else(self):
01615 pass
01616
01617 def handle_return(self):
01618 tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
01619 if not tokens:
01620 return Return(self.current_token.start, self.current_token.end, None)
01621 return Return(tokens[0].start, tokens[0].end, tokens)
01622
01623 def handle_goto(self):
01624 tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';')
01625 assert len(tokens) == 1, str(tokens)
01626 return Goto(tokens[0].start, tokens[0].end, tokens[0].name)
01627
01628 def handle_try(self):
01629 pass
01630
01631 def handle_catch(self):
01632 pass
01633
01634 def handle_throw(self):
01635 pass
01636
01637 def handle_while(self):
01638 pass
01639
01640 def handle_do(self):
01641 pass
01642
01643 def handle_for(self):
01644 pass
01645
01646 def handle_break(self):
01647 self._IgnoreUpTo(tokenize.SYNTAX, ';')
01648
01649 def handle_continue(self):
01650 self._IgnoreUpTo(tokenize.SYNTAX, ';')
01651
01652
01653 def BuilderFromSource(source, filename):
01654 """Utility method that returns an AstBuilder from source code.
01655
01656 Args:
01657 source: 'C++ source code'
01658 filename: 'file1'
01659
01660 Returns:
01661 AstBuilder
01662 """
01663 return AstBuilder(tokenize.GetTokens(source), filename)
01664
01665
01666 def PrintIndentifiers(filename, should_print):
01667 """Prints all identifiers for a C++ source file.
01668
01669 Args:
01670 filename: 'file1'
01671 should_print: predicate with signature: bool Function(token)
01672 """
01673 source = utils.ReadFile(filename, False)
01674 if source is None:
01675 sys.stderr.write('Unable to find: %s\n' % filename)
01676 return
01677
01678
01679 builder = BuilderFromSource(source, filename)
01680 try:
01681 for node in builder.Generate():
01682 if should_print(node):
01683 print(node.name)
01684 except KeyboardInterrupt:
01685 return
01686 except:
01687 pass
01688
01689
01690 def PrintAllIndentifiers(filenames, should_print):
01691 """Prints all identifiers for each C++ source file in filenames.
01692
01693 Args:
01694 filenames: ['file1', 'file2', ...]
01695 should_print: predicate with signature: bool Function(token)
01696 """
01697 for path in filenames:
01698 PrintIndentifiers(path, should_print)
01699
01700
01701 def main(argv):
01702 for filename in argv[1:]:
01703 source = utils.ReadFile(filename)
01704 if source is None:
01705 continue
01706
01707 print('Processing %s' % filename)
01708 builder = BuilderFromSource(source, filename)
01709 try:
01710 entire_ast = filter(None, builder.Generate())
01711 except KeyboardInterrupt:
01712 return
01713 except:
01714
01715 traceback.print_exc()
01716 else:
01717 if utils.DEBUG:
01718 for ast in entire_ast:
01719 print(ast)
01720
01721
01722 if __name__ == '__main__':
01723 main(sys.argv)