gccxmlparser.py

来自「Boost provides free peer-reviewed portab」· Python 代码 · 共 475 行 · 第 1/2 页

PY
475
字号
# Copyright Bruno da Silva de Oliveira 2003. Use, modification and # distribution is subject to the Boost Software License, Version 1.0.# (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt)from declarations import *# try to use cElementTree if avaiabletry:    from cElementTree import ElementTree    except ImportError:    # fall back to the normal elementtree    from elementtree.ElementTree import ElementTreefrom xml.parsers.expat import ExpatErrorfrom copy import deepcopyfrom utils import enumerate#==============================================================================# Exceptions#==============================================================================class InvalidXMLError(Exception): passclass ParserError(Exception): passclass InvalidContextError(ParserError): pass#==============================================================================# GCCXMLParser#==============================================================================class GCCXMLParser(object):    'Parse a GCC_XML file and extract the top-level declarations.'        interested_tags = {'Class':0, 'Function':0, 'Variable':0, 'Enumeration':0}        def Parse(self, filename):        self.elements = self.GetElementsFromXML(filename)        # high level declarations        self.declarations = []        self._names = {}        # parse the elements        for id in self.elements:            element, decl = self.elements[id]            if decl is None:                 try:                    self.ParseElement(id, element)                except InvalidContextError:                    pass # ignore those nodes with invalid context                          # (workaround gccxml bug)             def Declarations(self):        return self.declarations    def AddDecl(self, decl):        if decl.FullName() in self._names:            decl.is_unique= False            for d in self.declarations:                if d.FullName() == decl.FullName():                    d.is_unique = False        self._names[decl.FullName()] = 0        self.declarations.append(decl)            def ParseElement(self, id, element):        method = 'Parse' + element.tag        if hasattr(self, method):            func = getattr(self, method)            func(id, element)        else:            self.ParseUnknown(id, element)                def GetElementsFromXML(self,filename):        'Extracts a dictionary of elements from the gcc_xml file.'                tree = ElementTree()        try:            tree.parse(filename)        except ExpatError:            raise InvalidXMLError, 'Not a XML file: %s' % filename        root = tree.getroot()        if root.tag != 'GCC_XML':            raise InvalidXMLError, 'Not a valid GCC_XML file'        # build a dictionary of id -> element, None        elementlist = root.getchildren()        elements = {}        for element in elementlist:            id = element.get('id')            if id:                elements[id] = element, None        return elements    def GetDecl(self, id):        if id not in self.elements:            if id == '_0':                raise InvalidContextError, 'Invalid context found in the xml file.'            else:                 msg = 'ID not found in elements: %s' % id                raise ParserError, msg        elem, decl = self.elements[id]        if decl is None:            self.ParseElement(id, elem)            elem, decl = self.elements[id]            if decl is None:                raise ParserError, 'Could not parse element: %s' % elem.tag        return decl        def GetType(self, id):        def Check(id, feature):            pos = id.find(feature)            if pos != -1:                id = id[:pos] + id[pos+1:]                return True, id            else:                return False, id        const, id = Check(id, 'c')        volatile, id = Check(id, 'v')        restricted, id = Check(id, 'r')        decl = self.GetDecl(id)        if isinstance(decl, Type):            res = deepcopy(decl)            if const:                res.const = const            if volatile:                 res.volatile = volatile            if restricted:                res.restricted = restricted        else:            res = Type(decl.FullName(), const)            res.volatile = volatile            res.restricted = restricted        return res                                        def GetLocation(self, location):        file, line = location.split(':')        file = self.GetDecl(file)        return file, int(line)            def Update(self, id, decl):        element, _ = self.elements[id]        self.elements[id] = element, decl            def ParseUnknown(self, id, element):        name = '__Unknown_Element_%s' % id        decl = Unknown(name)        self.Update(id, decl)                    def ParseNamespace(self, id, element):        namespace = element.get('name')        context = element.get('context')        if context:            outer = self.GetDecl(context)            if not outer.endswith('::'):                outer += '::'            namespace = outer + namespace        if namespace.startswith('::'):            namespace = namespace[2:]        self.Update(id, namespace)    def ParseFile(self, id, element):        filename = element.get('name')        self.Update(id, filename)            def ParseVariable(self, id, element):        # in gcc_xml, a static Field is declared as a Variable, so we check        # this and call the Field parser.        context = self.GetDecl(element.get('context'))        if isinstance(context, Class):            self.ParseField(id, element)            elem, decl = self.elements[id]            decl.static = True        else:            namespace = context            name = element.get('name')                                type_ = self.GetType(element.get('type'))            location = self.GetLocation(element.get('location'))            variable = Variable(type_, name, namespace)            variable.location = location            self.AddDecl(variable)            self.Update(id, variable)            def GetArguments(self, element):        args = []        for child in element:            if child.tag == 'Argument':                type = self.GetType(child.get('type'))                type.default = child.get('default')                                args.append(type)        return args        def GetExceptions(self, exception_list):        if exception_list is None:            return None        exceptions = []        for t in exception_list.split():            exceptions.append(self.GetType(t))        return exceptions    def ParseFunction(self, id, element, functionType=Function):        '''functionType is used because a Operator is identical to a normal         function, only the type of the function changes.'''        name = element.get('name')        returns = self.GetType(element.get('returns'))        namespace = self.GetDecl(element.get('context'))        location = self.GetLocation(element.get('location'))        params = self.GetArguments(element)        incomplete = bool(int(element.get('incomplete', 0)))        throws = self.GetExceptions(element.get('throw', None))        function = functionType(name, namespace, returns, params, throws)         function.location = location        self.AddDecl(function)        self.Update(id, function)    def ParseOperatorFunction(self, id, element):        self.ParseFunction(id, element, Operator)            def GetHierarchy(self, bases):               '''Parses the string "bases" from the xml into a list of tuples of Base

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?