⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgmllib.py

📁 mallet是自然语言处理、机器学习领域的一个开源项目。
💻 PY
📖 第 1 页 / 共 2 页
字号:
"""A parser for SGML, using the derived class as a static DTD."""# XXX This only supports those SGML features used by HTML.# XXX There should be a way to distinguish between PCDATA (parsed# character data -- the normal case), RCDATA (replaceable character# data -- only char and entity references and end tags are special)# and CDATA (character data -- only end tags are special).  RCDATA is# not supported at all.import markupbaseimport re__all__ = ["SGMLParser"]# Regular expressions used for parsinginteresting = re.compile('[&<]')incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|'                           '<([a-zA-Z][^<>]*|'                              '/([a-zA-Z][^<>]*)?|'                              '![^<>]*)?')entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')charref = re.compile('&#([0-9]+)[^0-9]')starttagopen = re.compile('<[>a-zA-Z]')shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/')shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/')piclose = re.compile('>')endbracket = re.compile('[<>]')commentclose = re.compile(r'--\s*>')tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*')attrfind = re.compile(    r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*'    r'(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./:;+*%?!&$\(\)_#=~\'"]*))?')class SGMLParseError(RuntimeError):    """Exception raised for all parse errors."""    pass# SGML parser base class -- find tags and call handler functions.# Usage: p = SGMLParser(); p.feed(data); ...; p.close().# The dtd is defined by deriving a class which defines methods# with special names to handle tags: start_foo and end_foo to handle# <foo> and </foo>, respectively, or do_foo to handle <foo> by itself.# (Tags are converted to lower case for this purpose.)  The data# between tags is passed to the parser by calling self.handle_data()# with some data as argument (the data may be split up in arbitrary# chunks).  Entity references are passed by calling# self.handle_entityref() with the entity reference as argument.class SGMLParser(markupbase.ParserBase):    def __init__(self, verbose=0):        """Initialize and reset this instance."""        self.verbose = verbose        self.reset()    def reset(self):        """Reset this instance. Loses all unprocessed data."""        self.rawdata = ''        self.stack = []        self.lasttag = '???'        self.nomoretags = 0        self.literal = 0        markupbase.ParserBase.reset(self)    def setnomoretags(self):        """Enter literal mode (CDATA) till EOF.        Intended for derived classes only.        """        self.nomoretags = self.literal = 1    def setliteral(self, *args):        """Enter literal mode (CDATA).        Intended for derived classes only.        """        self.literal = 1    def feed(self, data):        """Feed some data to the parser.        Call this as often as you want, with as little or as much text        as you want (may include '\n').  (This just saves the text,        all the processing is done by goahead().)        """        self.rawdata = self.rawdata + data        self.goahead(0)    def close(self):        """Handle the remaining data."""        self.goahead(1)    def error(self, message):        raise SGMLParseError(message)    # Internal -- handle data as far as reasonable.  May leave state    # and data to be processed by a subsequent call.  If 'end' is    # true, force handling all data as if followed by EOF marker.    def goahead(self, end):        rawdata = self.rawdata        i = 0        n = len(rawdata)        while i < n:            if self.nomoretags:                self.handle_data(rawdata[i:n])                i = n                break            match = interesting.search(rawdata, i)            if match: j = match.start()            else: j = n            if i < j:                self.handle_data(rawdata[i:j])            i = j            if i == n: break            if rawdata[i] == '<':                if starttagopen.match(rawdata, i):                    if self.literal:                        self.handle_data(rawdata[i])                        i = i+1                        continue                    k = self.parse_starttag(i)                    if k < 0: break                    i = k                    continue                if rawdata.startswith("</", i):                    k = self.parse_endtag(i)                    if k < 0: break                    i = k                    self.literal = 0                    continue                if self.literal:                    if n > (i + 1):                        self.handle_data("<")                        i = i+1                    else:                        # incomplete                        break                    continue                if rawdata.startswith("<!--", i):                    k = self.parse_comment(i)                    if k < 0: break                    i = k                    continue                if rawdata.startswith("<?", i):                    k = self.parse_pi(i)                    if k < 0: break                    i = i+k                    continue                if rawdata.startswith("<!", i):                    # This is some sort of declaration; in "HTML as                    # deployed," this should only be the document type                    # declaration ("<!DOCTYPE html...>").                    k = self.parse_declaration(i)                    if k < 0: break                    i = k                    continue            elif rawdata[i] == '&':                if self.literal:                    self.handle_data(rawdata[i])                    i = i+1                    continue                match = charref.match(rawdata, i)                if match:                    name = match.group(1)                    self.handle_charref(name)                    i = match.end(0)                    if rawdata[i-1] != ';': i = i-1                    continue                match = entityref.match(rawdata, i)                if match:                    name = match.group(1)                    self.handle_entityref(name)                    i = match.end(0)                    if rawdata[i-1] != ';': i = i-1                    continue            else:                self.error('neither < nor & ??')            # We get here only if incomplete matches but            # nothing else            match = incomplete.match(rawdata, i)            if not match:                self.handle_data(rawdata[i])                i = i+1                continue            j = match.end(0)            if j == n:                break # Really incomplete            self.handle_data(rawdata[i:j])            i = j        # end while        if end and i < n:            self.handle_data(rawdata[i:n])            i = n        self.rawdata = rawdata[i:]        # XXX if end: check for empty stack    # Internal -- parse comment, return length or -1 if not terminated    def parse_comment(self, i, report=1):        rawdata = self.rawdata        if rawdata[i:i+4] != '<!--':            self.error('unexpected call to parse_comment()')        match = commentclose.search(rawdata, i+4)        if not match:            return -1        if report:            j = match.start(0)            self.handle_comment(rawdata[i+4: j])        return match.end(0)    # Extensions for the DOCTYPE scanner:    _decl_otherchars = '='    # Internal -- parse processing instr, return length or -1 if not terminated    def parse_pi(self, i):        rawdata = self.rawdata        if rawdata[i:i+2] != '<?':            self.error('unexpected call to parse_pi()')        match = piclose.search(rawdata, i+2)        if not match:            return -1        j = match.start(0)        self.handle_pi(rawdata[i+2: j])        j = match.end(0)        return j-i    __starttag_text = None    def get_starttag_text(self):        return self.__starttag_text    # Internal -- handle starttag, return length or -1 if not terminated    def parse_starttag(self, i):        self.__starttag_text = None        start_pos = i        rawdata = self.rawdata        if shorttagopen.match(rawdata, i):            # SGML shorthand: <tag/data/ == <tag>data</tag>            # XXX Can data contain &... (entity or char refs)?            # XXX Can data contain < or > (tag characters)?            # XXX Can there be whitespace before the first /?            match = shorttag.match(rawdata, i)            if not match:                return -1            tag, data = match.group(1, 2)            self.__starttag_text = '<%s/' % tag            tag = tag.lower()            k = match.end(0)            self.finish_shorttag(tag, data)            self.__starttag_text = rawdata[start_pos:match.end(1) + 1]            return k        # XXX The following should skip matching quotes (' or ")        match = endbracket.search(rawdata, i+1)

⌨️ 快捷键说明

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