Synopsis - Cross-Reference
File: Synopsis/ASG.py1# 2# Copyright (C) 2000 Stefan Seefeld 3# Copyright (C) 2000 Stephen Davies 4# All rights reserved. 5# Licensed to the public under the terms of the GNU LGPL (>= 2), 6# see the file COPYING for details. 7# 8 9"""Abstract Syntax Tree classes. 10 11This file contains classes which encapsulate nodes in the ASG. The base class 12is the Declaration class that encapsulates a named declaration. All names used 13are scoped tuples. 14 15Also defined in module scope are the constants DEFAULT, PUBLIC, PROTECTED and 16PRIVATE. 17""" 18 19# Accessibility constants 20DEFAULT = 0 21PUBLIC = 1 22PROTECTED = 2 23PRIVATE = 3 24 25def ccmp(a,b): 26 """Compares classes of two objects""" 27 return cmp(type(a),type(b)) or cmp(a.__class__,b.__class__) 28 29 30class Error: 31 """Exception class used by ASG internals.""" 32 33 def __init__(self, err): 34 self.err = err 35 def __repr__(self): 36 return self.err 37 38 39class Debugger(type): 40 """Wrap the object's 'accept' method, printing out the visitor's type. 41 Useful for tracing visitors visiting declarations.""" 42 43 def __init__(cls, name, bases, dict): 44 45 accept = dict['accept'] 46 "The original instancemethod." 47 48 def accept_wrapper(self, visitor): 49 "The wrapper. The original 'accept' method is part of its closure." 50 print '%s accepting %s.%s'%(self.__class__.__name__, 51 visitor.__module__, 52 visitor.__class__.__name__) 53 accept(self, visitor) 54 55 setattr(cls, 'accept', accept_wrapper) 56 57 58class TypeId(object): 59 """Type-id abstract class.""" 60 61 def __init__(self, language): 62 self.language = language 63 64 def accept(self, visitor): 65 """visitor pattern accept. @see Visitor""" 66 pass 67 68 def __cmp__(self, other): 69 "Comparison operator" 70 return cmp(id(self),id(other)) 71 72class NamedTypeId(TypeId): 73 """Named type abstract class""" 74 75 def __init__(self, language, name): 76 super(NamedTypeId, self).__init__(language) 77 self.name = name 78 79class BuiltinTypeId(NamedTypeId): 80 """Class for builtin type-ids""" 81 82 def __init__(self, language, name): 83 super(BuiltinTypeId, self).__init__(language, name) 84 def accept(self, visitor): visitor.visit_builtin_type_id(self) 85 def __cmp__(self, other): 86 "Comparison operator" 87 return ccmp(self,other) or cmp(self.name,other.name) 88 def __str__(self): return str(self.name) 89 90class DependentTypeId(NamedTypeId): 91 """Class for template dependent type-ids""" 92 93 def __init__(self, language, name): 94 super(DependentTypeId, self).__init__(language, name) 95 def accept(self, visitor): visitor.visit_dependent_type_id(self) 96 def __cmp__(self, other): 97 "Comparison operator" 98 return ccmp(self,other) or cmp(self.name,other.name) 99 def __str__(self): return str(self.name) 100 101class UnknownTypeId(NamedTypeId): 102 """Class for not (yet) known type-ids.""" 103 base = TypeId 104 def __init__(self, language, name): 105 super(UnknownTypeId, self).__init__(language, name) 106 self.link = name 107 def resolve(self, language, name, link): 108 """Associate this type-id with an external reference, instead of a declaration.""" 109 self.base.language = language 110 self.name = name 111 self.link = link 112 def accept(self, visitor): visitor.visit_unknown_type_id(self) 113 def __cmp__(self, other): 114 "Comparison operator" 115 return ccmp(self,other) or cmp(self.name,other.name) 116 def __str__(self): return str(self.name) 117 118class DeclaredTypeId(NamedTypeId): 119 """Class for declared types""" 120 121 def __init__(self, language, name, declaration): 122 super(DeclaredTypeId, self).__init__(language, name) 123 self.declaration = declaration 124 125 def accept(self, visitor): visitor.visit_declared_type_id(self) 126 def __cmp__(self, other): 127 "Comparison operator" 128 return ccmp(self,other) or cmp(self.name,other.name) 129 def __str__(self): return str(self.name) 130 131class TemplateId(DeclaredTypeId): 132 """Class for template-ids.""" 133 134 def __init__(self, language, name, declaration, parameters): 135 136 super(TemplateId, self).__init__(language, name, declaration) 137 self.parameters = parameters 138 def accept(self, visitor): visitor.visit_template_id(self) 139 def __cmp__(self, other): 140 "Comparison operator" 141 return ccmp(self,other) or cmp(self.parameters,other.parameters) 142 def __str__(self): 143 return "template<%s>%s"%(','.join([str(p) for p in self.parameters]), str(self.name)) 144 145class ModifierTypeId(TypeId): 146 """Class for alias types with modifiers (such as 'const', '&', etc.)""" 147 148 def __init__(self, language, alias, premod, postmod): 149 super(ModifierTypeId, self).__init__(language) 150 self.alias = alias 151 self.premod = premod 152 self.postmod = postmod 153 154 def accept(self, visitor): visitor.visit_modifier_type_id(self) 155 156 def __cmp__(self, other): 157 "Comparison operator" 158 return (ccmp(self,other) 159 or cmp(self.alias,other.alias) 160 or cmp(self.premod,other.premod) 161 or cmp(self.postmod,other.postmod)) 162 def __str__(self): 163 return "%s%s%s"%(''.join(['%s '%s for s in self.premod]), 164 str(self.alias), 165 ''.join(self.postmod)) 166 167class ArrayTypeId(TypeId): 168 """A modifier that adds array dimensions to a type-id.""" 169 170 def __init__(self, language, alias, sizes): 171 super(ArrayId, self).__init__(language) 172 self.alias = alias 173 self.sizes = sizes 174 def accept(self, visitor): visitor.visit_array_type_id(self) 175 def __cmp__(self, other): 176 "Comparison operator" 177 return (ccmp(self,other) 178 or cmp(self.alias,other.alias) 179 or cmp(self.sizes,other.sizes)) 180 def __str__(self): 181 return "%s%s"%(str(self.alias), 182 ''.join(['[%d]'%s for s in self.sizes])) 183 184class ParametrizedTypeId(TypeId): 185 """Class for parametrized type-id instances.""" 186 187 def __init__(self, language, template, parameters): 188 189 super(ParametrizedTypeId, self).__init__(language) 190 self.template = template 191 self.parameters = parameters 192 193 def accept(self, visitor): visitor.visit_parametrized_type_id(self) 194 195 def __cmp__(self, other): 196 "Comparison operator" 197 return ccmp(self,other) or cmp(self.template,other.template) 198 def __str__(self): 199 return "%s<%s>"%('::'.join(self.template.name), 200 ','.join([str(a) for a in self.parameters])) 201 202class FunctionTypeId(TypeId): 203 """Class for function (pointer) types.""" 204 def __init__(self, language, return_type, premod, parameters): 205 206 super(FunctionTypeId, self).__init__(language) 207 self.return_type = return_type 208 self.premod = premod 209 self.parameters = parameters 210 211 def accept(self, visitor): visitor.visit_function_type_id(self) 212 213 214class Dictionary(dict): 215 """Dictionary extends the builtin 'dict' by adding a lookup method to it.""" 216 217 def lookup(self, name, scopes): 218 """locate 'name' in one of the scopes""" 219 for s in scopes: 220 scope = list(s) 221 while len(scope) > 0: 222 if self.has_key(scope + name): 223 return self[scope + name] 224 else: del scope[-1] 225 if self.has_key(name): 226 return self[name] 227 return None 228 229 def merge(self, dict): 230 """merge in a foreign dictionary, overriding already defined types only 231 if they are of type 'Unknown'.""" 232 for i in dict.keys(): 233 if self.has_key(i): 234 if isinstance(self[i], UnknownTypeId): 235 self[i] = dict[i] 236 else: 237 pass 238 else: self[i] = dict[i] 239 240 241class Declaration(object): 242 """Declaration base class. Every declaration has a name, type, 243 accessibility and annotations. The default accessibility is DEFAULT except for 244 C++ where the Parser always sets it to one of the other three. """ 245 246 #__metaclass__ = Debugger 247 248 def __init__(self, file, line, type, name): 249 250 self.file = file 251 """SourceFile instance this declaration is part of.""" 252 self.line = line 253 """The line number of this declaration.""" 254 self.name = name 255 """The (fully qualified) name of the declared object.""" 256 self.type = type 257 """A string describing the (language-specific) type of the declared object.""" 258 self.accessibility = DEFAULT 259 """Accessibility descriptor for the declared object.""" 260 self.annotations = {} 261 """A dictionary holding any annotations of this object.""" 262 263 def accept(self, visitor): 264 """Visit the given visitor""" 265 visitor.visit_declaration(self) 266 267 268class Builtin(Declaration): 269 """A node for internal use only.""" 270 271 def accept(self, visitor): visitor.visit_builtin(self) 272 273 274class UsingDirective(Builtin): 275 """Import one module's content into another.""" 276 277 def accept(self, visitor): visitor.visit_using_directive(self) 278 279 280class UsingDeclaration(Builtin): 281 """Import a declaration into this module.""" 282 283 def __init__(self, file, line, type, name, alias): 284 285 super(UsingDeclaration, self).__init__(file, line, type, name) 286 self.alias = alias 287 288 def accept(self, visitor): 289 visitor.visit_using_declaration(self) 290 291 292class Macro(Declaration): 293 """A preprocessor macro. Note that macros are not strictly part of the 294 ASG, and as such are always in the global scope. A macro is "temporary" if 295 it was #undefined in the same file it was #defined in.""" 296 297 def __init__(self, file, line, type, name, parameters, text): 298 299 Declaration.__init__(self, file, line, type, name) 300 self.parameters = parameters 301 self.text = text 302 303 def accept(self, visitor): visitor.visit_macro(self) 304 305 306class Forward(Declaration): 307 """Forward declaration""" 308 309 def __init__(self, file, line, type, name, is_template_specialization = False): 310 311 Declaration.__init__(self, file, line, type, name) 312 self.template = None 313 self.is_template_specialization = is_template_specialization 314 self.primary_template = None 315 self.specializations = [] 316 317 def accept(self, visitor): 318 319 visitor.visit_forward(self) 320 321 322class Group(Declaration): 323 """Base class for groups which contain declarations. 324 This class doesn't correspond to any language construct. 325 Rather, it may be used with comment-embedded grouping tags 326 to regroup declarations that are to appear together in the 327 manual.""" 328 329 def __init__(self, file, line, type, name): 330 331 Declaration.__init__(self, file, line, type, name) 332 self.declarations = [] 333 334 def accept(self, visitor): 335 336 visitor.visit_group(self) 337 338 339class Scope(Declaration): 340 """Base class for scopes (named groups).""" 341 342 def __init__(self, file, line, type, name): 343 344 Declaration.__init__(self, file, line, type, name) 345 self.declarations = [] 346 347 def accept(self, visitor): visitor.visit_scope(self) 348 349 350class Module(Scope): 351 """Module class""" 352 def __init__(self, file, line, type, name): 353 354 Scope.__init__(self, file, line, type, name) 355 356 def accept(self, visitor): visitor.visit_module(self) 357 358 359class MetaModule(Module): 360 """Module Class that references all places where this Module occurs""" 361 362 def __init__(self, type, name): 363 364 Scope.__init__(self, None, "", type, name) 365 self.module_declarations = [] 366 367 def accept(self, visitor): visitor.visit_meta_module(self) 368 369 370class Inheritance(object): 371 """Inheritance class. This class encapsulates the information about an 372 inheritance, such as attributes like 'virtual' and 'public' """ 373 374 def __init__(self, type, parent, attributes): 375 self.type = type 376 self.parent = parent 377 self.attributes = attributes 378 379 def accept(self, visitor): visitor.visit_inheritance(self) 380 381 382class Class(Scope): 383 384 def __init__(self, file, line, type, name, is_template_specialization = False): 385 386 Scope.__init__(self, file, line, type, name) 387 self.parents = [] 388 self.is_template_specialization = is_template_specialization 389 self.primary_template = None 390 391 def accept(self, visitor): visitor.visit_class(self) 392 393 394class ClassTemplate(Scope): 395 396 def __init__(self, file, line, type, name, 397 template = None, is_template_specialization = False): 398 399 Scope.__init__(self, file, line, type, name) 400 self.parents = [] 401 self.template = template 402 self.is_template_specialization = is_template_specialization 403 self.primary_template = None 404 self.specializations = [] 405 406 def accept(self, visitor): visitor.visit_class_template(self) 407 408 409class Typedef(Declaration): 410 411 def __init__(self, file, line, type, name, alias, constr): 412 Declaration.__init__(self, file, line, type, name) 413 self.alias = alias 414 self.constr = constr 415 416 def accept(self, visitor): visitor.visit_typedef(self) 417 418 419class Enumerator(Declaration): 420 """Enumerator of an Enum. Enumerators represent the individual names and 421 values in an enum.""" 422 423 def __init__(self, file, line, name, value): 424 Declaration.__init__(self, file, line, "enumerator", name) 425 self.value = value 426 427 def accept(self, visitor): visitor.visit_enumerator(self) 428 429class Enum(Declaration): 430 """Enum declaration. The actual names and values are encapsulated by 431 Enumerator objects.""" 432 433 def __init__(self, file, line, name, enumerators): 434 435 Declaration.__init__(self, file, line, "enum", name) 436 self.enumerators = enumerators[:] 437 #FIXME: the Cxx parser will append a Builtin('eos') to the 438 #list of enumerators which we need to extract here. 439 self.eos = None 440 if self.enumerators and isinstance(self.enumerators[-1], Builtin): 441 self.eos = self.enumerators.pop() 442 443 def accept(self, visitor): visitor.visit_enum(self) 444 445 446class Variable(Declaration): 447 """Variable definition""" 448 449 def __init__(self, file, line, type, name, vtype, constr): 450 Declaration.__init__(self, file, line, type, name) 451 self.vtype = vtype 452 self.constr = constr 453 454 def accept(self, visitor): visitor.visit_variable(self) 455 456 457class Const(Declaration): 458 """Constant declaration. A constant is a name with a type and value.""" 459 460 def __init__(self, file, line, type, ctype, name, value): 461 Declaration.__init__(self, file, line, type, name) 462 self.ctype = ctype 463 self.value = value 464 465 def accept(self, visitor): visitor.visit_const(self) 466 467 468class Parameter(object): 469 """Function Parameter""" 470 471 def __init__(self, premod, type, postmod, name='', value=''): 472 self.premodifier = premod 473 self.type = type 474 self.postmodifier = postmod 475 self.name = name 476 self.value = value 477 478 def accept(self, visitor): visitor.visit_parameter(self) 479 480 def __cmp__(self, other): 481 "Comparison operator" 482 #print "Parameter.__cmp__" 483 return cmp(self.type,other.type) 484 def __str__(self): 485 return "%s%s%s"%(' '.join(self.premodifier), 486 str(self.type), 487 ' '.join(self.postmodifier)) 488 489class Function(Declaration): 490 """Function declaration. 491 Note that function names are stored in mangled form to allow overriding. 492 Formatters should use the real_name to extract the unmangled name.""" 493 494 def __init__(self, file, line, type, premod, return_type, postmod, name, real_name): 495 Declaration.__init__(self, file, line, type, name) 496 self._real_name = real_name 497 self.premodifier = premod 498 self.return_type = return_type 499 self.parameters = [] 500 self.postmodifier = postmod 501 self.exceptions = [] 502 503 real_name = property(lambda self: self.name[:-1] + (self._real_name,)) 504 505 def accept(self, visitor): visitor.visit_function(self) 506 507 def __cmp__(self, other): 508 "Recursively compares the typespec of the function" 509 return ccmp(self,other) or cmp(self.parameters, other.parameters) 510 511 512class FunctionTemplate(Function): 513 514 def __init__(self, file, line, type, premod, return_type, postmod, name, real_name, template = None): 515 Function.__init__(self, file, line, type, premod, return_type, postmod, name, real_name) 516 self.template = template 517 518 def accept(self, visitor): visitor.visit_function_template(self) 519 520 521class Operation(Function): 522 """Operation class. An operation is related to a Function and is currently 523 identical. 524 """ 525 def __init__(self, file, line, type, premod, return_type, postmod, name, real_name): 526 Function.__init__(self, file, line, type, premod, return_type, postmod, name, real_name) 527 528 def accept(self, visitor): visitor.visit_operation(self) 529 530 531class OperationTemplate(Operation): 532 533 def __init__(self, file, line, type, premod, return_type, postmod, name, real_name, template = None): 534 Operation.__init__(self, file, line, type, premod, return_type, postmod, name, real_name) 535 self.template = template 536 537 def accept(self, visitor): visitor.visit_operation_template(self) 538 539 540class Visitor(object): 541 """Visitor for ASG nodes""" 542 543 def visit_builtin_type_id(self, type): pass 544 def visit_unknown_type_id(self, type): pass 545 def visit_declared_type_id(self, type): pass 546 def visit_modifier_type_id(self, type): pass 547 def visit_array_type_id(self, type): pass 548 def visit_template_id(self, type): pass 549 def visit_parametrized_type_id(self, type): pass 550 def visit_function_type_id(self, type): pass 551 def visit_dependent_type_id(self, type): pass 552 553 def visit_declaration(self, node): pass 554 def visit_builtin(self, node): 555 """Visit a Builtin instance. By default do nothing. Processors who 556 operate on Builtin nodes have to provide an appropriate implementation.""" 557 pass 558 def visit_using_directive(self, node): self.visit_builtin(node) 559 def visit_using_declaration(self, node): self.visit_builtin(node) 560 def visit_macro(self, node): self.visit_declaration(node) 561 def visit_forward(self, node): self.visit_declaration(node) 562 def visit_group(self, node): 563 self.visit_declaration(node) 564 for d in node.declarations: d.accept(self) 565 def visit_scope(self, node): 566 self.visit_declaration(node) 567 for d in node.declarations: d.accept(self) 568 def visit_module(self, node): self.visit_scope(node) 569 def visit_meta_module(self, node): self.visit_module(node) 570 def visit_class(self, node): self.visit_scope(node) 571 def visit_class_template(self, node): self.visit_class(node) 572 def visit_typedef(self, node): self.visit_declaration(node) 573 def visit_enumerator(self, node): self.visit_declaration(node) 574 def visit_enum(self, node): 575 self.visit_declaration(node) 576 for e in node.enumerators: 577 e.accept(self) 578 if node.eos: 579 node.eos.accept(self) 580 def visit_variable(self, node): self.visit_declaration(node) 581 def visit_const(self, node): self.visit_declaration(node) 582 def visit_function(self, node): 583 self.visit_declaration(node) 584 for parameter in node.parameters: parameter.accept(self) 585 def visit_function_template(self, node): self.visit_function(node) 586 def visit_operation(self, node): self.visit_function(node) 587 def visit_operation_template(self, node): self.visit_operation(node) 588 def visit_parameter(self, node): pass 589 def visit_inheritance(self, node): pass 590 591class ASG(object): 592 593 def __init__(self, declarations = None, types = None): 594 595 self.declarations = declarations or [] 596 self.types = types or Dictionary() 597 598 def copy(self): 599 600 return type(self)(self.declarations[:], 601 self.types.copy()) 602 603 def merge(self, other): 604 605 self.declarations.extend(other.declarations) 606 self.types.merge(other.types) 607 608
Generated on Tue May 13 02:39:40 2008 by
synopsis (version 0.10)
synopsis (version 0.10)