1 """
2 MoinMoin - C++ Source Parser
3
4 Copyright (c) 2002 by Taesu Pyo <bigflood@hitel.net>
5 All rights reserved.
6
7 """
8
9
10 import cgi, string, re, sys
11
12
13
14
15 class ReservedWordFormat:
16 def __init__(self,color,bold=1):
17 self.color = color
18 self.bold = bold
19 def formatString(self,word):
20 if self.bold:
21 return '<font color="%s"><b>%s</b></font>' % (self.color,word)
22 else:
23 return '<font color="%s">%s</font>' % (self.color,word)
24
25
26 class Parser:
27 """
28 """
29 formatting_rules = r"""(?P<CommentStart>/[*])
30 (?P<LineComment>//.*$)
31 (?P<StringStart>L?")
32 (?P<Char>'\\.'|'[^\\]')
33 (?P<Number>[0-9](\.[0-9]*)?(eE[+-][0-9])?[flFLuU]?|0[xX][0-9a-fA-F]+)
34 (?P<Preprc>^\s*#(.*\\\n)*.*$)
35 (?P<ID>[a-zA-Z_][0-9a-zA-Z_]*)
36 (?P<SPChar>[~!%^&*()+=|\[\]:;,.<>/?{}-])"""
37
38 reserved_words = ['struct','class','union','enum',
39 'int','float','double','signed','unsigned','char','short','void','bool',
40 'long','register','auto','operator',
41 'static','const','private','public','protected','virtual','explicit',
42 'new','delete','this',
43 'if','else','while','for','do','switch','case','default','sizeof',
44 'dynamic_cast','static_cast','const_cast','reinterpret_cast','typeid',
45 'try','catch','throw','throws','return','continue','break','goto']
46
47 reserved_words2 = ['extern', 'volatile', 'typedef', 'friend',
48 '__declspec', 'inline','__asm','thread','naked','dllimport','dllexport',
49 'namespace','using', 'template','typename','goto']
50
51 special_words = ['std','string','vector','map','set','cout','cin','cerr']
52
53 constant_words = ['true','false','NULL']
54
55 ID_format = {}
56 for w in reserved_words:
57 ID_format[w] = ReservedWordFormat('#4040ff')
58
59 for w in reserved_words2:
60 ID_format[w] = ReservedWordFormat('#0080ff')
61
62 for w in special_words:
63 ID_format[w] = ReservedWordFormat('#0000ff',bold=0)
64
65 for w in constant_words:
66 ID_format[w] = ReservedWordFormat('#008080')
67
68 ID_def_format = ReservedWordFormat('#000000',bold=0)
69
70
71 def __init__(self, raw, request, **kw):
72 self.raw = raw
73 self.rawout = kw.get('out', sys.stdout)
74 self.line_count = 0
75
76
77 def write(self, s):
78 self.rawout.write(s)
79
80
81 def format(self, formatter, form):
82 """ Send the text.
83 """
84 scan_re = re.compile(self.formatting_rules.replace('\n','|'),re.M)
85 self.end_comment_re = re.compile(r'[*]/',re.M)
86 self.end_string_re = re.compile(r'[^\\]$|[^\\](\\\\)*"',re.M)
87
88 self.lastpos = 0
89 self.line = self.raw
90
91 self.write('<pre><font face="Lucida,Courier New" color="#C00000">')
92
93 match = scan_re.search(self.line)
94
95 while match and self.lastpos < len(self.line):
96
97 self.write_no_match(self.line[self.lastpos:match.start()])
98 self.lastpos = match.end() + (match.end() == self.lastpos)
99
100 self.write_match(match)
101
102
103 match = scan_re.search(self.line, self.lastpos)
104
105 self.write_no_match(self.line[self.lastpos:])
106
107 self.write('</font></pre>')
108
109
110 def write_no_match(self,text):
111 text = cgi.escape(text)
112 text = string.expandtabs(text)
113 self.write(text)
114
115 def write_match(self,match):
116 for type, hit in match.groupdict().items():
117 if not hit: continue
118 apply(getattr(self, 'write_match_' + type), (hit,))
119
120
121 def write_match_CommentStart(self,hit):
122 self.write('<font color="#808080">' + str(hit))
123 match = self.end_comment_re.search(self.line, self.lastpos)
124 if not match:
125 next_lastpos = len(self.line)
126 else:
127 next_lastpos = match.end() + (match.end() == self.lastpos)
128 self.write(self.line[self.lastpos:next_lastpos])
129 self.lastpos = next_lastpos
130 self.write('</font>')
131
132 def write_match_StringStart(self,hit):
133 self.write('<font color="#004080">' + str(hit))
134
135 if self.line[self.lastpos] == '"':
136 next_lastpos = self.lastpos + 1
137 else:
138 match = self.end_string_re.search(self.line, self.lastpos)
139 if not match:
140 next_lastpos = len(self.line)
141 else:
142 next_lastpos = match.end() + (match.end() == self.lastpos)
143 self.write(self.line[self.lastpos:next_lastpos])
144 self.lastpos = next_lastpos
145 self.write('</font>')
146
147 def write_match_Char(self,hit):
148 self.write('<font color="#004080">%s</font>' % hit)
149
150 def write_match_LineComment(self,hit):
151 self.write('<font color="#808080">%s</font>' % hit)
152
153 def write_match_Preprc(self,hit):
154 self.write('<font color="#804000">%s</font>' % cgi.escape(hit))
155
156 def write_match_Number(self,hit):
157 self.write('<font color="#008080"><B>%s</B></font>' % hit)
158
159 def write_match_ID(self,hit):
160 c = self.ID_format.get(hit,self.ID_def_format)
161 self.write(c.formatString(hit))
162
163 def write_match_SPChar(self,hit):
164 self.write('<font color="#0000C0">%s</font>' % cgi.escape(hit))
165
166
167 if __name__ == "__main__":
168 import os, sys
169
170
171 source = open('test.cpp').read()
172 Parser(source, None, out = open('test.html', 'wt')).format(None, None)
173
174
175 if os.name == "nt":
176 os.system("explorer test.html")
177 else:
178 os.system("netscape test.html &")