def getTypes(memberElem) : #defines a node, and is not defined within the section of another node def isTopNode(elem) : return definesNode(elem) and not lib.hasAncestorElement(elem.parentNode, definesNode) assert memberElem.tagName == "member" if memberElem.hasAttribute("linkend") and \ memberElem.getAttribute("linkend").find("node.") != 0 : id = memberElem.getAttribute("linkend") sect = memberElem.ownerDocument.getElementById(id) if sect == None : raise Exception("no element with id '%s'" % id) return map(getTitle, filter(isTopNode, lib.descendantElements(sect))) return [lib.textValue(memberElem)]
def extractNodeTypes(filePath) : def definesNode(elem) : return elem.getAttribute("xml:id").find("node.") == 0 def isFamily(node) : return lib.hasAncestorElement( node, lambda x: x.getAttribute("xml:id") == "family-node-types" ) def isTree(elem) : for child in lib.childElements(elem) : if child.getAttribute("role") == "layout" : return True return False def getTitle(elem) : assert definesNode(elem) return lib.textValue(elem.getElementsByTagName("title")[0]) def isExpressionNodeType(elem) : def isNonExec(elem) : return lib.hasAncestorElement( elem, lambda x: x.getAttribute("xml:id") == "non-executable" ) def isNestedNode(elem) : return lib.hasAncestorElement( elem, lambda x: x.getAttribute("xml:id").find("node.") == 0 ) assert definesNode(elem) return \ not isFamily(elem) and \ not isNonExec(elem) and \ not isNestedNode(elem.parentNode) def extractFamilyType(sectElem) : def findTypes() : listElem = filter( lambda x: x.getAttribute("role") == "family-members", lib.childElements(sectElem) )[0] def getTypes(memberElem) : #defines a node, and is not defined within the section of another node def isTopNode(elem) : return definesNode(elem) and not lib.hasAncestorElement(elem.parentNode, definesNode) assert memberElem.tagName == "member" if memberElem.hasAttribute("linkend") and \ memberElem.getAttribute("linkend").find("node.") != 0 : id = memberElem.getAttribute("linkend") sect = memberElem.ownerDocument.getElementById(id) if sect == None : raise Exception("no element with id '%s'" % id) return map(getTitle, filter(isTopNode, lib.descendantElements(sect))) return [lib.textValue(memberElem)] rv = [] for member in lib.childElements(listElem) : rv += getTypes(member) return rv typename = getTitle(sectElem) types = findTypes() return { "category" : "family", "typename" : typename, "members" : types } def extractTreeType(sectElem) : def parseChild(member) : text = lib.textValue(member) tokens = text.split(" ") child = {} #count (e.g. *) if tokens[0] in ["*", "+", "?"] : child["count"] = tokens.pop(0) else : child["count"] = "1" #typename (e.g. "alpha-beta-gamma") child["typename"] = tokens.pop(0) #label (e.g. "alpha beta gamma") if len(tokens) > 0 : child["label"] = " ".join(tokens) return child layoutElem = filter( lambda x: x.getAttribute("role") == "layout", lib.childElements(sectElem) )[0] members = layoutElem.getElementsByTagName("member") return { "category" : "tree", "typename" : getTitle(sectElem), "layout" : map(parseChild, members) } def extractTerminalType(elem) : return { "category" : "terminal", "typename" : getTitle(elem) } def extractNodeType(elem) : assert definesNode(elem) if isFamily(elem) : return extractFamilyType(elem) elif isTree(elem) : return extractTreeType(elem) else : return extractTerminalType(elem) doc = DOM.parse(filePath) lib.setXmlId(doc) nodeTypes = map(extractNodeType, filter(definesNode, lib.descendantElements(doc))) #ensure no types are listed twice (it's happened) typenames = set(map(lambda x: x["typename"], nodeTypes)) assert len(nodeTypes) == len(typenames) return nodeTypes