python基础教程:即时标记

来源:互联网 发布:mac vmware使用教程 编辑:程序博客网 时间:2024/06/04 19:47

class Handler:
    """
    处理从Parser调用的方法的对象。
    """
    def callback(self, prefix, name, *args):
        method = getattr(self, prefix + name, None)
        if callable(method):
             return method(*args)
         
    def start(self, name):
        self.callback('start_', name)

    def end(self, name):
        self.callback('end_', name)

    #返回一个新的函数,这个函数会被当成re.sub中的替换函数来使用(这就是采用一个匹配的对象作为唯一参数的原因)
    def sub(self, name):
        def substitution(math):
            result = self.callback('sub_', name, match)
            if result is None:
                  match.group(0)
            return result
        return substitution



class HTMLRenderer(Handler):
    """
    用于生成HTML具体处理程序
    """
    def start_document(self):
        print '<html><head><title>...</title></head><body>'

    def end_document(self):
        print '</body></html>'
     
    def start_paragraph(self):
        print '<p>'

    def end_paragraph(self):
        print '</p>'

    def sub_emphasis(self, match):
        return '<em>%s</em>' % match.group(1)
    
    def sub_url(self, match):
        return '<a href="mail to:%s">%s</a>' % (match.group(1), match.group(1))


======================util.py===========================


def lines(infile):
    for line in infile:
        yield line
        yield '\n'
        
def blocks(infile):
    block = []
    for line in lines(infile):
        if line.strip():
            block.append(line)
        elif block:
            yield ''.join(block).strip()
            block = []


====================== rules.py =========================



class Rule:
    """
    所有规则的基类
    """
    def action(self, block, handler):
        handler.start(self.type)
        handler.feed(block)
        handler.end(self.type)
        return True
    

class HeadingRule(Rule):
    """
    标题占一行,最多70个字符,并且不以冒号结尾
    """
    type = 'heading'
    def condition(self, block):
        return not '\n' in block and len(block) <= 70 and not block[-1] == ':'

    
class TitleRule(HeadingRule):
    """
    题目是文档的第一个块,但前提是它是大标题
    """
    type = 'title'
    first = True
    
    def condition(self, block):
        if not self.first:
            return False
        self.first = False
        return HeadingRule.condition(self, block)


class ListItemRule(Rule):
    """
    列表项是以连字符开始的段落,作为格式化的一部分,要移除连字符
    """
    type = 'listitem'
    def condition(self, block):
        return block[0] == '-'
    
    def action(self, block, handler):
        handler.start(self.type)
        handler.feed(block[1:].strip())
        handler.end(self.type)
        return True
    

class ListRule(ListItemRule):
    """
    列表从不是列表项的块和随后的列表项之间。在最后一个列表项之后结束
    """
    type = 'list'
    inside = False
    def condition(self, block):
        return True
    
    def action(self, block, handler):
        if not self.inside and ListItemRule.condition(self, block):
            handler.start(self.type)
        elif self.inside and not ListItemRule.conditions(self, block):
            handler.end(self.type)
            self.inside = False
        return False
    

class ParagraphRule(Rule):
    """
    段落只是其他规则并没有覆盖到的块
    """
    type = 'paragraph'
    def condition(self, block):
        return True
    

    

====================== markup.py ====================


import sys, re
from handlers import *
from util import *
from rules import *

class Parser:
    """
    语法分析器读取文本文件、应用规则并且控制处理程序
    """
    def __init__(self, handler):
        self.handler = handler
        self.rules = []
        self.filters = []
        
    def addRule(self, rule):
        self.rules.append(rule)
        
    def addFilter(self, pattern, name):
        def filter(block, handler):
            return re.sub(pattern, handler.sub(name).block)
        self.filters.append(filter)
        
    def parse(self, file):
        self.handler.start('document')
        for bolock in blocks(file):
            for filter in self.filters:
                block = filter(block, self.handler)
            for rule in self.rules:
                if rule.condition(block):
                    last = rule.action(block, self.handler)
                    if last:
                        break
        self.handler.end('document')
        
        
class BasicTextParser(Parser):
    """
    在构造函数中增加规则和过滤器的具体语法分析器
    """
    def __init__(self, handler):
        Parser.__init__(self, handler)
        self.addRule(ListRule())
        self.addRule(ListItemRule())
        self.addRule(TitleRule())
        self.addRule(HeadingRule())
        self.addRule(ParagraphRule())
        
        self.addFilter(r'\*(.+?)\*', 'emphasis')
        self.addFilter(r'(http://[A-Za-z]+)', 'url')
        self.addRule(r'([\.a-zA-Z+]@[\.a-zA-Z]+[a-zA-Z]+)', 'mail')

        
handler = HTMLRenderer()
parser = BasicTextParser(handler)

parser.parse(sys.stdin)