~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/plugins/codebrowser/codebrowser/gentag/feritetags.py

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
###############################################################################
 
2
# Name: feritetags.py                                                         #
 
3
# Purpose: Generate Tags for Ferite Documents                                 #
 
4
# Author: Cody Precord <cprecord@editra.org>                                  #
 
5
# Copyright: (c) 2008 Cody Precord <staff@editra.org>                         #
 
6
# License: wxWindows License                                                  #
 
7
###############################################################################
 
8
 
 
9
"""
 
10
FILE: haxetags.py
 
11
AUTHOR: Cody Precord
 
12
LANGUAGE: Python
 
13
SUMMARY:
 
14
  Generate a DocStruct object that captures the structure of a Ferite document.
 
15
Supports parsing of Namespaces, Classes, Protocols, Functions.
 
16
 
 
17
@todo: Currently Parsing of Namespaces within Namespaces is not supported
 
18
 
 
19
"""
 
20
 
 
21
__author__ = "Cody Precord <cprecord@editra.org>"
 
22
__svnid__ = "$Id: feritetags.py 52805 2008-03-25 09:56:14Z CJP $"
 
23
__revision__ = "$Revision: 52805 $"
 
24
 
 
25
#--------------------------------------------------------------------------#
 
26
# Dependancies
 
27
import taglib
 
28
import parselib
 
29
 
 
30
#--------------------------------------------------------------------------#
 
31
 
 
32
def GenerateTags(buff):
 
33
    """Create a DocStruct object that represents a Ferite document
 
34
    @param buff: a file like buffer object (StringIO)
 
35
 
 
36
    """
 
37
    rtags = taglib.DocStruct()
 
38
 
 
39
    # Setup document structure
 
40
    rtags.SetElementDescription('namespace', "Namespaces")
 
41
    rtags.SetElementDescription('class', "Class Definitions")
 
42
    rtags.SetElementDescription('protocol', "Protocols")
 
43
    rtags.SetElementDescription('function', "Function Definitions")
 
44
    rtags.SetElementPriority('namespace', 4)
 
45
    rtags.SetElementPriority('class', 3)
 
46
    rtags.SetElementPriority('protocol', 2)
 
47
    rtags.SetElementPriority('function', 1)
 
48
 
 
49
    # Variables for tracking parse state
 
50
    incomment = False    # Inside a comment
 
51
    innamespace = False  # Inside a namespace
 
52
    inclass = False      # Inside a class defintion
 
53
    inprotocol = False   # Inside a protocol
 
54
    infundef = False     # Inside a function definition
 
55
    lastnspace = None    # Last Namespace
 
56
    lastclass = None     # Last Class
 
57
    lastprotocol = None  # Last Protocol
 
58
    lastfun = None       # last Function
 
59
    openb = 0            # Keep track of open brackets for scope resolution
 
60
 
 
61
    def InSubScope():
 
62
        return innamespace or inclass or inprotocol or infundef
 
63
 
 
64
    # Parse the contents of the buffer
 
65
    for lnum, line in enumerate(buff):
 
66
        line = line.strip()
 
67
        llen = len(line)
 
68
        idx = 0
 
69
        while idx < len(line):
 
70
            # Skip Whitespace
 
71
            idx = parselib.SkipWhitespace(line, idx)
 
72
 
 
73
            # Check for comments
 
74
            if line[idx:].startswith(u'/*'):
 
75
                idx += 2
 
76
                incomment = True
 
77
            elif line[idx:].startswith(u'//'):
 
78
                break # go to next line
 
79
            elif line[idx:].startswith(u'*/'):
 
80
                idx += 2
 
81
                incomment = False
 
82
 
 
83
            # At end of line
 
84
            if idx >= llen:
 
85
                break
 
86
 
 
87
            # Look for tags
 
88
            if incomment:
 
89
                idx += 1
 
90
            elif line[idx] == u'{':
 
91
                idx += 1
 
92
                openb += 1
 
93
                # Namespace/Class/Protocol names must be followed by a {
 
94
                if not InSubScope() and lastnspace is not None:
 
95
                    innamespace = True
 
96
                    rtags.AddElement('namespace', lastnspace)
 
97
                elif not inclass and lastclass is not None:
 
98
                    inclass = True
 
99
                    if lastnspace is not None:
 
100
                        # Class is in a namespace
 
101
                        lastnspace.AddElement('class', lastclass)
 
102
                    else:
 
103
                        # Class is at the global scope
 
104
                        rtags.AddClass(lastclass)
 
105
                elif not InSubScope() and lastprotocol is not None:
 
106
                    inprotocol = True
 
107
                    rtags.AddElement('protocol', lastprotocol)
 
108
                elif lastfun is not None:
 
109
                    infundef = True
 
110
                    lastfun = None
 
111
                else:
 
112
                    pass
 
113
            elif line[idx] == u'}':
 
114
                idx += 1
 
115
                openb -= 1
 
116
                # Check if the scope needs to change
 
117
                if innamespace and openb == 0:
 
118
                    innamespace = False
 
119
                    lastnspace = None
 
120
                elif innamespace and inclass and openb == 1:
 
121
                    inclass = False
 
122
                    lastclass = None
 
123
                elif (innamespace and inclass and infundef and openb == 2) or \
 
124
                     (innamespace and infundef and openb == 1):
 
125
                    infundef = False
 
126
                    lastfun = None
 
127
                elif inclass and openb == 0:
 
128
                    inclass = False
 
129
                    lastclass = None
 
130
                elif inclass and infundef and openb == 1:
 
131
                    infundef = False
 
132
                    lastfun = None
 
133
                elif inprotocol and openb == 0:
 
134
                    inprotocol = False
 
135
                    lastprotocol = None
 
136
                elif inprotocol and infundef and openb == 1:
 
137
                    infundef = False
 
138
                    lastfun = None
 
139
                elif infundef and openb == 0:
 
140
                    infundef = False
 
141
                    lastfun = None
 
142
                else:
 
143
                    pass
 
144
            elif not infundef and parselib.IsToken(line, idx, u'class'):
 
145
                # Skip whitespace
 
146
                idx = parselib.SkipWhitespace(line, idx + 5)
 
147
                name = parselib.GetFirstIdentifier(line[idx:])
 
148
                if name is not None:
 
149
                    idx += len(name) # Move past the class name
 
150
                    lastclass = taglib.Class(name, lnum)
 
151
            elif not infundef and not inclass and \
 
152
                 parselib.IsToken(line, idx, 'namespace'):
 
153
                idx = parselib.SkipWhitespace(line, idx + 9)
 
154
                name = GetElementName(line[idx:])
 
155
                if name is not None:
 
156
                    idx += len(name)
 
157
                    lastnspace = taglib.Namespace(name, lnum)
 
158
            elif parselib.IsToken(line, idx, u'protocol'):
 
159
                idx = parselib.SkipWhitespace(line, idx + 8)
 
160
                name = parselib.GetFirstIdentifier(line[idx:])
 
161
                if name is not None:
 
162
                    idx += len(name)
 
163
                    lastprotocol = Protocol(name, lnum)
 
164
            elif parselib.IsToken(line, idx, u'function'):
 
165
                # Skip whitespace
 
166
                idx = parselib.SkipWhitespace(line, idx + 8)
 
167
                name = parselib.GetFirstIdentifier(line[idx:])
 
168
                if name is not None:
 
169
                    lastfun = name
 
170
                    # Skip whitespace
 
171
                    idx = parselib.SkipWhitespace(line, idx + len(name))
 
172
 
 
173
                    if line[idx] != u'(':
 
174
                        continue
 
175
 
 
176
                    tfun = taglib.Function(name, lnum)
 
177
                    if innamespace and not inclass and lastnspace:
 
178
                        lastnspace.AddElement('function', tfun)
 
179
                    elif inclass and lastclass is not None:
 
180
                        lastclass.AddMethod(taglib.Method(name, lnum, lastclass.GetName()))
 
181
                    elif inprotocol and lastprotocol is not None:
 
182
                        lastprotocol.AddElement('function', tfun)
 
183
                    else:
 
184
                        rtags.AddFunction(tfun)
 
185
            else:
 
186
                idx += 1
 
187
 
 
188
    return rtags
 
189
 
 
190
#-----------------------------------------------------------------------------#
 
191
class Protocol(taglib.Scope):
 
192
    """Protocol Code Object"""
 
193
    def __init__(self, name, line, scope=None):
 
194
        taglib.Scope.__init__(self, name, line, "protocol", scope)
 
195
 
 
196
def GetElementName(line):
 
197
    """Get the first element name on the given line, ignoring whitespace and
 
198
    language keywords.
 
199
    @param line: string
 
200
    @return: string or None
 
201
 
 
202
    """
 
203
    for part in line.split():
 
204
        name = parselib.GetFirstIdentifier(part)
 
205
        if name is not None and name not in FERITE_KW:
 
206
            return name
 
207
        else:
 
208
            continue
 
209
    return None
 
210
 
 
211
FERITE_KW = ("false null self super true abstract alias and arguments "
 
212
             "attribute_missing break case class closure conformsToProtocol "
 
213
             "constructor continue default deliver destructor diliver "
 
214
             "directive do else extends eval final fix for function global "
 
215
             "handle if iferr implements include instanceof isa "
 
216
             "method_missing modifies monitor namespace new or private "
 
217
             "protected protocol public raise recipient rename return "
 
218
             "static switch uses using while")
 
219
 
 
220
#-----------------------------------------------------------------------------#
 
221
# Test
 
222
if __name__ == '__main__':
 
223
    import sys
 
224
    import StringIO
 
225
    fhandle = open(sys.argv[1])
 
226
    txt = fhandle.read()
 
227
    fhandle.close()
 
228
    tags = GenerateTags(StringIO.StringIO(txt))
 
229
    print "\n\nElements:"
 
230
    for element in tags.GetElements():
 
231
        print "\n%s:" % element.keys()[0]
 
232
        for val in element.values()[0]:
 
233
            print "%s [%d]" % (val.GetName(), val.GetLine())
 
234
    print "END"