File: Synopsis/ASG.py 1
2
3
4
5
6
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
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
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
438
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
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 Thu Apr 16 16:27:16 2009 by
synopsis (version devel)