def add_doc(last_member, docstring, new_docstring): if last_member is None: docstring.text += new_docstring else: try: element = last_member.find("docstring") except Exception: element = E.docstring(new_docstring) last_member.append(element) element.text += new_docstring
def typedef_parse(typename, bases, block): from .parse import divide_blocks, parse_block from .macros import get_macros macros = get_macros() if not is_valid_silktype(typename): raise SilkSyntaxError("Invalid silk type definition: invalid type name: ''%s'" % typename) for base in bases: if not is_valid_silktype(base, permit_array=True): raise SilkSyntaxError("Invalid silk type definition: cannot inherit from non-silk type '%s'" % base) methodblock = None tree = E.silk( typename=typename, ) for base in bases: tree.append(E.base(base)) docstring = E.docstring("") tree.append(docstring) lines = divide_blocks(block) inside_def = False inside_methodblock = False curr_indent = 0 last_member = None while lines: line = lines[0].strip() line_tabs_as_spaces = lines[0].replace('\t', " ") lines = lines[1:] if not line: continue if line.startswith("##"): line = line[2:].lstrip() if len(line.split()) < 2: raise SilkSyntaxError(line) name = line.split()[0] typedef_block(tree, name, line[len(name) + 1:]) continue if line.find("#") == 0: continue if not inside_def and line.startswith('"""'): line = line[3:] end_quotes_index = line.index('"""') between_quotes = line[:end_quotes_index] add_doc(last_member, docstring, between_quotes) continue if inside_def: indent = len(line_tabs_as_spaces) - len(line_tabs_as_spaces.lstrip()) if indent == curr_indent: inside_def = False if not inside_def: if line_tabs_as_spaces.lstrip().startswith("def "): curr_indent = len(line_tabs_as_spaces) - len(line_tabs_as_spaces.lstrip()) inside_def = True if inside_def or line_tabs_as_spaces.lstrip().startswith("@"): if not inside_methodblock: methodblock = E.methodblock("") tree.append(methodblock) inside_methodblock = True methodblock.text += "\n " + "\n ".join(line_tabs_as_spaces.split("\n")) continue else: if inside_methodblock: methodblock.text += "\n " inside_methodblock = False assert not inside_methodblock and not inside_def #bugcheck name, title, block, block_comment = parse_block(line) if block is not None: if title != "" and title is not None: raise SilkSyntaxError("Malformed block statement, must be <name> {...}\n%s" % (line)) spaces = None block_lines = block.split('\n') reformatted_block_lines = [] for line in block_lines: if not line.strip(): continue # Find indentation if spaces is None: spaces = len(line) - len(line.lstrip()) reformatted_block_lines.append(line.rstrip('\n')[spaces:]) reformatted_block = "\n " + "\n ".join(reformatted_block_lines) + "\n " memberblock = None if last_member is not None: memberblock = typedef_memberblock(tree, name, reformatted_block) if memberblock is not None: if memberblock[2]: last_member.attrib[memberblock[0]] = memberblock[1] else: last_member.append(getattr(E, memberblock[0])(memberblock[1])) if memberblock is None: typedef_block(tree, name, reformatted_block) last_member = None elif block_comment and not name: add_doc(last_member, docstring, block_comment) else: if not title: raise SilkSyntaxError("Malformed %s statement: NOT_REQUIRED title" % (name, line)) split_title = title.split() if name == "Delete": if len(split_title) != 1: raise SilkSyntaxError("Malformed Delete statement: %s" % line) tree.append(E.delete(title)) elif name in "Include": if len(split_title) != 1: raise SilkSyntaxError("Malformed Include statement: %s" % line) tree.append(E.include(title)) else: newlines = None for macro in macros: new_block = macro(name, title) if not new_block: continue newlines = divide_blocks(new_block) break if newlines is not None: lines[:] = newlines + lines continue init_statement = None if len(split_title) > 1: if split_title[1] != "=": raise SilkSyntaxError("Malformed member statement: %s" % line) title = split_title[0] init_statement = " ".join(split_title[2:]) if not is_valid_silktype(name, permit_array=True): raise TypeError("Invalid member name '%s'" % name) member = E.member(E.name(title), E.type(name)) if init_statement is not None: member.append(E.init(init_statement)) tree.append(member) last_member = member if inside_methodblock: methodblock.text += "\n " if not len(docstring.text): tree.remove(docstring) return tree