Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Formatter/ASCII.py
1| # $Id: ASCII.py,v 1.32 2003/01/27 06:53:36 chalky Exp $
2| #
3| # This file is a part of Synopsis.
4| # Copyright (C) 2000, 2001 Stefan Seefeld
5| # Copyright (C) 2000, 2001 Stephen Davies
6| #
7| # Synopsis is free software; you can redistribute it and/or modify it
8| # under the terms of the GNU General Public License as published by
9| # the Free Software Foundation; either version 2 of the License, or
10| # (at your option) any later version.
11| #
12| # This program is distributed in the hope that it will be useful,
13| # but WITHOUT ANY WARRANTY; without even the implied warranty of
14| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15| # General Public License for more details.
16| #
17| # You should have received a copy of the GNU General Public License
18| # along with this program; if not, write to the Free Software
19| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20| # 02111-1307, USA.
21| #
22| # $Log: ASCII.py,v $
23| # Revision 1.32 2003/01/27 06:53:36 chalky
24| # Added macro support for C++.
25| #
26| # Revision 1.31 2002/10/27 12:06:11 chalky
27| # Fix funcptr parameters
28| #
29| # Revision 1.30 2002/10/26 04:15:53 chalky
30| # Fix typo in method name
31| #
32| # Revision 1.29 2002/10/20 15:38:07 chalky
33| # Much improved template support, including Function Templates.
34| #
35| # Revision 1.28 2001/08/02 03:25:09 chalky
36| # Reworked handling of enumerators for use in synopsis-qt GUI
37| #
38| # Revision 1.27 2001/07/28 02:41:34 chalky
39| # Minor sanity fix
40| #
41| # Revision 1.26 2001/07/19 04:00:17 chalky
42| # New .syn file format. Added -b, -c flags
43| #
44| # Revision 1.25 2001/05/25 13:45:49 stefan
45| # fix problem with getopt error reporting
46| #
47| # Revision 1.24 2001/02/13 06:55:23 chalky
48| # Made synopsis -l work again
49| #
50| # Revision 1.23 2001/02/13 06:35:20 chalky
51| # Added config_obj to format() args to prevent exception.
52| #
53| # Revision 1.22 2001/02/06 16:02:23 chalky
54| # Fixes
55| #
56| # Revision 1.21 2001/01/31 06:51:24 stefan
57| # add support for '-v' to all modules; modified toc lookup to use additional url as prefix
58| #
59| # Revision 1.20 2001/01/24 01:38:36 chalky
60| # Added docstrings to all modules
61| #
62| # Revision 1.19 2001/01/22 19:54:41 stefan
63| # better support for help message
64| #
65| # Revision 1.18 2001/01/22 17:06:15 stefan
66| # added copyright notice, and switched on logging
67| #
68| """
69| Outputs the AST in plain ascii format similar to input.
70| """
71|
72| # THIS-IS-A-FORMATTER
73| import sys, getopt, os, os.path, string
74| from Synopsis.Core import Type, AST, Util
75|
76| verbose = 0
77| comment_str = "// %s\n"
78|
79| class ASCIIFormatter(AST.Visitor, Type.Visitor):
80| """
81| outputs as ascii. This is to test for features
82| still missing. The output should be compatible
83| with the input...
84| """
85| def __init__(self, os):
86| self.__indent = 0
87| self.__istring = " "
88| self.__os = os
89| self.__scope = []
90| self.__axs = AST.DEFAULT
91| self.__axs_stack = []
92| self.__axs_string = ('default:\n','public:\n','protected:\n','private:\n')
93| self.__enumers = []
94| self.__id_holder = None
95| def indent(self):
96| self.__os.write(self.__istring * self.__indent)
97| def incr(self): self.__indent = self.__indent + 1
98| def decr(self): self.__indent = self.__indent - 1
99| def scope(self): return self.__scope
100| def set_scope(self, name): self.__scope = list(name)
101| def enterScope(self, name): self.__scope.append(name),self.incr()
102| def leaveScope(self): self.__scope.pop(),self.decr()
103| def write(self, text): self.__os.write(text)
104|
105| def formatType(self, type, id_holder = None):
106| if type is None: return '(unknown)'
107| if id_holder: self.__id_holder = id_holder
108| type.accept(self)
109| if id_holder: self.__id_holder = None
110| return self.__type
111|
112| #################### Type Visitor ###########################################
113|
114| def visitBaseType(self, type):
115| self.__type = Util.ccolonName(type.name())
116|
117| def visitDependent(self, type):
118| self.__type = type.name()[-1]
119|
120| def visitUnknown(self, type):
121| self.__type = Util.ccolonName(type.name(), self.scope())
122|
123| def visitDeclared(self, type):
124| self.__type = Util.ccolonName(type.name(), self.scope())
125|
126| def visitModifier(self, type):
127| aliasStr = self.formatType(type.alias())
128| premod = map(lambda x:x+" ", type.premod())
129| self.__type = "%s%s%s"%(string.join(premod,''), aliasStr, string.join(type.postmod(),''))
130|
131| def visitParametrized(self, type):
132| temp = self.formatType(type.template())
133| params = map(self.formatType, type.parameters())
134| self.__type = "%s<%s>"%(temp,string.join(params, ", "))
135|
136| def visitFunctionType(self, type):
137| ret = self.formatType(type.returnType())
138| params = map(self.formatType, type.parameters())
139| premod = string.join(type.premod(),'')
140| if self.__id_holder:
141| ident = self.__id_holder[0]
142| del self.__id_holder[0]
143| else:
144| ident = ''
145| self.__type = "%s(%s%s)(%s)"%(ret,premod,ident,string.join(params,", "))
146|
147| def visitTemplate(self, type):
148| self.visitDeclared(type)
149| #self.__type = "template<"+string.join(map(self.formatType, type.parameters()),",")+">"+self.__type
150|
151| ### AST visitor
152|
153| def visitDeclaration(self, decl):
154| axs = decl.accessibility()
155| if axs != self.__axs:
156| self.decr(); self.indent(); self.incr()
157| self.write(self.__axs_string[axs])
158| self.__axs = axs
159| self.writeComments(decl.comments())
160|
161| def visitMacro(self, macro):
162| self.visitDeclaration(macro)
163| self.indent()
164| params = ''
165| if macro.parameters() is not None:
166| params = '(' + string.join(macro.parameters(), ', ') + ')'
167| self.write("#define %s%s %s\n"%(macro.name()[-1], params, macro.text()))
168|
169| def writeComments(self, comments):
170| for comment in comments:
171| text = comment.text()
172| if not text: continue
173| lines = string.split(text, "\n")
174| for line in lines:
175| self.indent()
176| self.write(comment_str%line)
177|
178| def visitTypedef(self, typedef):
179| self.visitDeclaration(typedef)
180| self.indent()
181| dstr = ""
182| # Figure out the type:
183| alias = self.formatType(typedef.alias())
184| # Figure out the declarators:
185| # for declarator in typedef.declarators():
186| # dstr = dstr + declarator.name()[-1]
187| # if declarator.sizes() is None: continue
188| # for size in declarator.sizes():
189| # dstr = dstr + "[%d]"
190| self.write("typedef %s %s;\n"%(
191| alias, typedef.name()[-1]
192| ))
193|
194| def visitModule(self, module):
195| self.visitDeclaration(module)
196| self.indent()
197| self.write("%s %s {\n"%(module.type(),module.name()[-1]))
198| self.enterScope(module.name()[-1])
199| #for type in module.types(): type.output(self)
200| for declaration in module.declarations():
201| declaration.accept(self)
202| self.leaveScope()
203| self.indent()
204| self.write("}\n")
205|
206| def visitMetaModule(self, module):
207| self.visitDeclaration(module)
208| for decl in module.module_declarations():
209| self.visitDeclaration(decl)
210| # since no comments:
211| self.visitModule(module)
212|
213| def visitClass(self, clas):
214| self.visitDeclaration(clas)
215| self.indent()
216| self.write("%s %s"%(clas.type(),clas.name()[-1]))
217| if len(clas.parents()):
218| self.write(": ")
219| p = []
220| for parent in clas.parents():
221| p.append(self.formatType(parent.parent()))
222| #p.append("%s"%(Util.ccolonName(parent.parent().name(),clas.name()),))
223| self.write(string.join(p, ", "))
224| self.write(" {\n")
225| self.enterScope(clas.name()[-1])
226| self.__axs_stack.append(self.__axs)
227| if clas.type() == 'struct': self.__axs = AST.PUBLIC
228| elif clas.type() == 'class': self.__axs = AST.PRIVATE
229| else: self.__axs = AST.DEFAULT
230| #for type in clas.types(): type.output(self)
231| #for operation in clas.operations(): operation.output(self)
232| for declaration in clas.declarations():
233| declaration.accept(self)
234| self.__axs = self.__axs_stack.pop()
235| self.leaveScope()
236| self.indent()
237| self.write("};\n")
238|
239| def visitInheritance(self, inheritance):
240| for attribute in inheritance.attributes(): self.write(attribute + " ")
241| self.write(inheritance.parent().identifier())
242|
243| def visitParameter(self, parameter):
244| spacer = lambda x: str(x)+" "
245| premod = string.join(map(spacer,parameter.premodifier()),'')
246| id_holder = [parameter.identifier()]
247| type = self.formatType(parameter.type(), id_holder)
248| postmod = string.join(map(spacer,parameter.postmodifier()),'')
249| name = ""
250| value = ""
251| if id_holder and len(parameter.identifier()) != 0:
252| name = " " + parameter.identifier()
253| if len(parameter.value()) != 0:
254| value = " = %s"%parameter.value()
255| self.__params.append(premod + type + postmod + name + value)
256|
257| def visitFunction(self, function):
258| self.visitOperation(function)
259|
260| def visitOperation(self, operation):
261| self.visitDeclaration(operation)
262| self.indent()
263| for modifier in operation.premodifier(): self.write(modifier + " ")
264| retStr = self.formatType(operation.returnType())
265| name = operation.realname()
266| if operation.language() == "IDL" and operation.type() == "attribute":
267| self.write("attribute %s %s"%(retStr,name[-1]))
268| else:
269| if operation.language() == "C++" and len(name)>1 and name[-1] in [name[-2],"~"+name[-2]]:
270| self.write("%s("%name[-1])
271| else:
272| if retStr: self.write(retStr+" ")
273| self.write("%s("%name[-1])
274| self.__params = []
275| for parameter in operation.parameters(): parameter.accept(self)
276| params = string.join(self.__params, ", ")
277| self.write(params + ")")
278| for modifier in operation.postmodifier(): self.write(modifier + " ")
279| self.write(";\n")
280|
281| def visitVariable(self, var):
282| self.visitDeclaration(var)
283| name = var.name
284| self.indent()
285| self.write("%s %s;\n"%(self.formatType(var.vtype()),var.name()[-1]))
286|
287| def visitEnum(self, enum):
288| self.visitDeclaration(enum)
289| self.indent()
290| istr = self.__istring * (self.__indent+1)
291| self.write("enum %s {"%enum.name()[-1])
292| self.__enumers = []
293| comma = ''
294| for enumer in enum.enumerators():
295| self.write(comma+'\n'+istr)
296| enumer.accept(self)
297| comma = ','
298| self.write("\n")
299| self.indent()
300| self.write("}\n")
301|
302| def visitEnumerator(self, enumer):
303| self.writeComments(enumer.comments())
304| if enumer.value() == "":
305| self.write("%s"%enumer.name()[-1])
306| else:
307| self.write("%s = %s"%(enumer.name()[-1], enumer.value()))
308|
309| def visitConst(self, const):
310| self.visitDeclaration(const)
311| ctype = self.formatType(const.ctype())
312| self.indent()
313| self.__os.write("%s %s = %s;\n"%(ctype,const.name()[-1],const.value()))
314|
315|
316| def usage():
317| """Print usage to stdout"""
318| print \
319| """
320| -o <file> Output file
321| -b Bold comments
322| -c <colour> Coloured comments, colour = 0 to 15
323| """
324|
325| def __parseArgs(args):
326| global output, verbose, show_bold, show_colour, comment_str
327| output = sys.stdout
328| show_bold = 0
329| show_colour = None
330| try:
331| opts,remainder = getopt.getopt(args, "o:vbc:")
332| except getopt.error, e:
333| sys.stderr.write("Error in arguments: " + str(e) + "\n")
334| sys.exit(1)
335|
336| for opt in opts:
337| o,a = opt
338|
339| if o == "-o": output = open(a, "w")
340| elif o == "-v": verbose = 1
341| elif o == "-b": show_bold = 1
342| elif o == "-c": show_colour = int(a)
343|
344| if show_colour is not None:
345| comment_str = "\033[3%d%sm// %%s\033[m\n"%(
346| show_colour % 8,
347| (show_colour >= 8) and ";1" or "")
348| elif show_bold:
349| comment_str = "\033[1m// %s\033[m\n"
350|
351| def print_types(types):
352| keys = types.keys()
353| keys.sort()
354| for name in keys:
355| type = types[name]
356| clas = type.__class__
357| if isinstance(type, Type.Declared):
358| clas = type.declaration().__class__
359| try:
360| print "%s\t%s"%(string.split(clas.__name__,'.')[-1], Util.ccolonName(name))
361| except:
362| print "name ==",name
363| raise
364|
365| def format(args, ast, config_obj):
366| __parseArgs(args)
367| formatter = ASCIIFormatter(output)
368| #for type in types:
369| # type.output(formatter)
370| for declaration in ast.declarations():
371| declaration.accept(formatter)
372|
373| # print_types(types)