File: Synopsis/Formatters/BoostBook.py 1
2
3
4
5
6
7
8
9"""a BoostBook formatter"""
10
11from Synopsis.Processor import Processor, Parameter
12from Synopsis import ASG
13
14import sys, getopt, os, os.path
15
16class Formatter(Processor, ASG.Visitor):
17 """
18 The type visitors should generate names relative to the current scope.
19 The generated references however are fully scoped names
20 """
21
22 def process(self, ir, **kwds):
23
24 self.set_parameters(kwds)
25 self.ir = self.merge_input(ir)
26
27 self.__os = open(self.output, 'w')
28 self.__scope = ()
29 self.__scopestack = []
30 self.__indent = 0
31 self.__type_label = ''
32
33 for d in ir.asg.declarations:
34 d.accept(self)
35
36 self.__os.close()
37
38 return self.ir
39
40 def scope(self): return self.__scope
41 def push_scope(self, newscope):
42
43 self.__scopestack.append(self.__scope)
44 self.__scope = newscope
45
46 def pop_scope(self):
47
48 self.__scope = self.__scopestack[-1]
49 del self.__scopestack[-1]
50
51 def write(self, text):
52 """Write some text to the output stream, replacing \n's with \n's and
53 indents."""
54
55 indent = ' ' * self.__indent
56 self.__os.write(text.replace('\n', '\n'+indent))
57
58 def start_entity(self, __type, **__params):
59 """Write the start of an entity, ending with a newline"""
60
61 param_text = ""
62 if __params: param_text = " " + string.join(map(lambda p:'%s="%s"'%(p[0].lower(), p[1]), __params.items()))
63 self.write("<" + __type + param_text + ">")
64 self.__indent = self.__indent + 2
65 self.write("\n")
66
67 def end_entity(self, type):
68 """Write the end of an entity, starting with a newline"""
69
70 self.__indent = self.__indent - 2
71 self.write("\n</" + type + ">")
72
73 def write_entity(self, __type, __body, **__params):
74 """Write a single entity on one line (though body may contain
75 newlines)"""
76
77 param_text = ""
78 if __params: param_text = " " + string.join(map(lambda p:'%s="%s"'%(p[0].lower(), p[1]), __params.items()))
79 self.write("<" + __type + param_text + ">")
80 self.__indent = self.__indent + 2
81 self.write(__body)
82 self.__indent = self.__indent - 2
83 self.write("</" + __type + ">")
84
85 def entity(self, __type, __body, **__params):
86 """Return but do not write the text for an entity on one line"""
87
88 param_text = ""
89 if __params: param_text = " " + string.join(map(lambda p:'%s="%s"'%(p[0].lower(), p[1]), __params.items()))
90 return "<%s%s>%s</%s>"%(__type, param_text, __body, __type)
91
92 def reference(self, ref, label):
93 """reference takes two strings, a reference (used to look up the symbol and generated the reference),
94 and the label (used to actually write it)"""
95
96 location = self.__toc.lookup(ref)
97 if location != "": return href("#" + location, label)
98 else: return span("type", str(label))
99
100 def label(self, ref):
101
102 location = self.__toc.lookup(str(ref))
103 ref = str(self.scope().prune(ref))
104 if location != "": return name("\"" + location + "\"", ref)
105 else: return ref
106
107 def type_label(self): return self.__type_label
108
109
110 def visit_builtin_type_id(self, type):
111
112 self.__type_ref = str(type.name)
113 self.__type_label = str(type.name)
114
115 def visit_unknown_type_id(self, type):
116
117 self.__type_ref = str(type.name)
118 self.__type_label = str(self.scope().prune(type.name))
119
120 def visit_declared_type_id(self, type):
121
122 self.__type_label = str(self.scope().prune(type.name))
123 self.__type_ref = str(type.name)
124
125 def visit_modifier_type_id(self, type):
126
127 type.alias.accept(self)
128 self.__type_ref = ''.join(type.premod) + ' ' + self.__type_ref + ' ' + ''.join(type.postmod)
129 self.__type_label = ''.join(type.premod) + ' ' + self.__type_label + ' ' + ''.join(type.postmod)
130
131 def visit_parametrized_type_id(self, type):
132
133 type.template.accept(self)
134 type_label = self.__type_label + "<"
135 parameters_label = []
136 for p in type.parameters:
137 p.accept(self)
138 parameters_label.append(self.__type_label)
139 self.__type_label = type_label + ', '.join(parameters_label) + '>'
140
141 def format_type(self, type):
142
143 type.accept(self)
144 return self.__type_label
145
146 def visit_function_type_id(self, type):
147
148
149 self.__type_ref = 'function_type'
150 self.__type_label = 'function_type'
151
152 def process_doc(self, doc):
153
154 text = doc.replace('\n\n', '</para><para>')
155 self.write(self.entity("para", text)+'\n')
156
157
158
159 def visit_declarator(self, node):
160 self.__declarator = node.name
161 for i in node.sizes:
162 self.__declarator[-1] = self.__declarator[-1] + '[%d]'%i
163
164 def visit_typedef(self, typedef):
165
166 self.start_entity("typedef", name=str(self.scope().prune(typedef.name)))
167 self.write_entity("type", self.format_type(typedef.alias))
168 self.end_entity("typedef")
169
170 def visit_variable(self, variable):
171
172 self.start_entity("fieldsynopsis")
173 variable.vtype.accept(self)
174 self.entity("type", self.type_label())
175 self.entity("varname", variable.name[-1])
176 self.end_entity("fieldsynopsis")
177
178 def visit_const(self, const):
179
180 print "sorry, <const> not implemented"
181
182 def visit_module(self, module):
183
184 self.start_entity("namespace", name=str(self.scope().prune(module.name)))
185 self.write("\n")
186 self.process_doc(module.annotations.get('doc', ''))
187 self.push_scope(module.name)
188 for declaration in module.declarations: declaration.accept(self)
189 self.pop_scope()
190 self.end_entity("namespace")
191
192 def visit_class(self, class_):
193
194 self.start_entity("class", name=str(self.scope().prune(class_.name)))
195
196 for p in class_.parents:
197 p.accept(self)
198 self.push_scope(class_.name)
199 if class_.annotations.has_key('doc'):
200 self.start_entity("purpose")
201 self.process_doc(class_.annotations.get['doc'])
202 self.end_entity("purpose")
203 for d in class_.declarations:
204 d.accept(self)
205 self.pop_scope()
206 self.end_entity("class")
207
208 def visit_inheritance(self, inheritance):
209
210 if len(inheritance.attributes()):
211 self.start_entity("inherit", access=inheritance.attributes()[0])
212 else:
213 self.start_entity("inherit")
214 self.write_entity("classname", self.format_type(inheritance.parent()))
215 self.end_entity("inherit")
216
217 def visit_parameter(self, parameter):
218
219 self.start_entity("parameter", name=parameter.name)
220 self.write_entity("param_type", self.format_type(parameter.type))
221
222
223 self.end_entity("parameter")
224 self.write("\n")
225
226 def visit_function(self, function):
227
228 self.start_entity("function", name=str(self.scope().prune(function.real_name)))
229 self.do_function(function)
230 self.end_entity("function")
231 self.write("\n")
232
233 def visit_operation(self, operation):
234
235 name = operation.name
236 tag = None
237 if len(name) > 1:
238 if name[-1] == name[-2]:
239 tag = "constructor"
240 self.start_entity(tag)
241 elif name[-1] == "~"+name[-2]:
242 tag = "destructor"
243 self.start_entity(tag)
244 if tag is None:
245 tag = "method"
246 self.start_entity(tag, name=str(self.scope().prune(operation.real_name)))
247 self.do_function(operation)
248 self.end_entity(tag)
249 self.write("\n")
250
251 def do_function(self, func):
252 """Stuff common to functions and methods, contructors, destructors"""
253
254 for parameter in func.parameters: parameter.accept(self)
255 if func.return_type:
256 self.write_entity("type", self.format_type(func.return_type))
257 self.write("\n")
258 if func.annotations.has_key('doc'):
259 self.start_entity("purpose")
260 self.process_doc(func.annotations['doc'])
261 self.end_entity("purpose")
262 self.write("\n")
263
264 if func.exceptions:
265 self.start_entity("throws")
266 for ex in func.exceptions:
267 self.write_entity("simpara", ex)
268 self.end_entity("throws")
269 self.write("\n")
270
271 def visit_enumerator(self, enumerator):
272
273 print "sorry, <enumerator> not implemented"
274
275 def visit_enum(self, enum):
276
277 print "sorry, <enum> not implemented"
278
279
Generated on Thu Apr 16 16:27:12 2009 by
synopsis (version devel)