013-正规式与正则表达式

013-正规式与正则表达式

难度:🟡 | 预计时间:90分钟 | 前置:012-非确定有限自动机NFA

学习目标

  • 理解正规式(正则表达式)的形式化定义和语法
  • 掌握正规式的基本运算:连接、并、Kleene星
  • 学会正规式与有限自动机的等价性证明
  • 理解正规式在编译器词法分析中的应用
  • 掌握正规式的优化和化简技术

内容正文

正规式的形式化定义

正规式(Regular Expression)是描述正则语言的代数表示法,它提供了一种简洁的方式来表达字符串模式。

递归定义

设Σ是有限字母表,Σ上的正规式定义如下:

  1. 基础情况

    • ∅(空集)是正规式
    • ε(空字符串)是正规式
    • 对于任意a ∈ Σ,a是正规式
  2. 递归情况

    • 如果r和s是正规式,则(r|s)是正规式(并运算)
    • 如果r和s是正规式,则(rs)是正规式(连接运算)
    • 如果r是正规式,则r*是正规式(Kleene星运算)
语义定义

每个正规式r定义一个语言L®:

  • L(∅) = ∅
  • L(ε) = {ε}
  • L(a) = {a},其中a ∈ Σ
  • L(r|s) = L® ∪ L(s)
  • L(rs) = L® · L(s) = {xy | x ∈ L®, y ∈ L(s)}
  • L(r*) = (L®)* = ∪_{i≥0} (L®)^i

正规式的语法和运算

运算符优先级
# 文件路径: examples/regex_precedence.py
# 正规式运算符优先级演示

class RegexPrecedence:
    """正规式运算符优先级和结合性"""
    
    PRECEDENCE = {
   
   
        '*': 3,    # Kleene星,最高优先级
        '+': 3,    # 正闭包
        '?': 3,    # 可选
        'CONCAT': 2,  # 连接运算(隐式)
        '|': 1     # 并运算,最低优先级
    }
    
    def __init__(self):
        self.examples = [
            # (表达式, 默认解析, 显式括号)
            ('ab|c', '(ab)|c', '((a)(b))|(c)'),
            ('a|bc', 'a|(bc)', '(a)|((b)(c))'),
            ('ab*', 'a(b*)', '(a)((b)*)'),
            ('(a|b)*', '(a|b)*', '((a)|(b))*'),
            ('a|b*c', 'a|(b*c)', '(a)|((b*)(c))'),
            ('ab|cd*', '(ab)|(cd*)', '((a)(b))|((c)(d*))'),
        ]
    
    def demonstrate_precedence(self):
        """演示运算符优先级"""
        print("=== 正规式运算符优先级演示 ===")
        print("优先级(高到低): * + ? > 连接 > |")
        print()
        
        for expr, default, explicit in self.examples:
            print(f"表达式: {
     
     expr}")
            print(f"  默认解析: {
     
     default}")
            print(f"  完全展开: {
     
     explicit}")
            print()
    
    def show_associativity(self):
        """演示结合性"""
        print("=== 运算符结合性 ===")
        
        associativity_examples = [
            ('a|b|c', '((a|b)|c)', '左结合'),
            ('abc', '((ab)c)', '左结合'),
            ('a***', '((a*)*)*', '左结合'),
        ]
        
        for expr, parsed, rule in associativity_examples:
            print(f"{
     
     expr}{
     
     parsed} ({
     
     rule})")
        print()

# 演示优先级和结合性
prec_demo = RegexPrecedence()
prec_demo.demonstrate_precedence()
prec_demo.show_associativity()
扩展运算符
# 文件路径: examples/extended_regex_operators.py
# 扩展正规式运算符实现

class ExtendedRegexOperators:
    """扩展的正规式运算符"""
    
    def __init__(self):
        self.operators = {
   
   
            '+': '正闭包(一次或多次)',
            '?': '可选(零次或一次)',
            '{n}': '精确重复n次',
            '{n,m}': '重复n到m次',
            '[abc]': '字符类(a或b或c)',
            '[^abc]': '否定字符类(除a、b、c外)',
            '.': '任意字符(通配符)',
            '^': '行首锚点',
            '$': '行尾锚点'
        }
    
    def expand_to_basic(self, extended_expr):
        """将扩展运算符转换为基本正规式"""
        expansions = {
   
   
            'a+': 'aa*',           # 正闭包
            'a?': '(ε|a)',         # 可选
            'a{3}': 'aaa',         # 精确重复
            'a{2,4}': 'aa(ε|a)(ε|a)',  # 范围重复(简化)
            '[abc]': '(a|b|c)',    # 字符类
            '[^abc]': '(d|e|f|...)', # 否定字符类(示例)
        }
        
        print("=== 扩展运算符到基本正规式的转换 ===")
        for ext, basic in expansions.items():
            print(f"{
     
     ext}{
     
     basic}")
        print()
        
        return expansions.get(extended_expr, extended_expr)
    
    def demonstrate_equivalences(self):
        """演示等价转换"""
        equivalences = [
            ('a+', 'aa*', '正闭包等价于:至少一个a'),
            ('a?', '(ε|a)', '可选等价于:空或一个a'),
            ('(a|b)+', '(a|b)(a|b)*', '正闭包的复合形式'),
            ('[0-9]', '(0|1|2|3|4|5|6|7|8|9)', '数字字符类'),
            ('a{2,3}', 'aa(ε|a)', '有界重复'),
        ]
        
        print("=== 扩展运算符等价性 ===")
        for original, equivalent, description in equivalences:
            print(f"{
     
     original}{
     
     equivalent}")
            print(f"  说明: {
     
     description}")
            print()

# 演示扩展运算符
ext_ops = ExtendedRegexOperators()
ext_ops.demonstrate_equivalences()

正规式与有限自动机的等价性

Kleene定理

Kleene定理:一个语言是正则语言当且仅当它可以用正规式表示。

证明分为两个方向:

  1. 正规式 → NFA(Thompson构造法)
  2. DFA → 正规式(状态消除法)
状态消除法:DFA到正规式
# 文件路径: examples/state_elimination.py
# 状态消除法:将DFA转换为正规式

class StateElimination:
    """状态消除法实现"""
    
    def __init__(self, dfa):
        self.dfa = dfa
        self.transitions = {
   
   }  # 广义转换函数,值为正规式
        self.states = set(dfa.states)
        
        # 初始化转换表
        self.initialize_transitions()
    
    def initialize_transitions(self):
        """初始化转换表为正规式"""
        # 为所有状态对初始化空转换
        for q1 in self.states:
            for q2 in self.states:
                self.transitions[(q1, q2)] = '∅'
        
        # 设置实际转换
        for (state, symbol), next_state in self.dfa.transitions.items():
            key = (state, next_state)
            if self.transitions[key] == '∅':
                self.transitions[key] = symbol
            else:
                # 合并多个转换
                self.transitions[key] = f"({
     
     self.transitions[key]}|{
     
     symbol})"
        
        # 设置自环(空字符串转换)
        for state in self.states:
            if self.transitions[(state, state)] == '∅':
                self.transitions[(state, state)] = 'ε'
            else:
                self.transitions[(state, state)] = f"(ε|{
     
     self.transitions[(state, state)]})"
    
    def eliminate_state(self, state_to_eliminate):
        """消除指定状态"""
        print(f"\n消除状态: {
     
     state_to_eliminate}")
        
        # 获取所有相关转换
        incoming = []  # 进入被消除状态的转换
        outgoing = []  # 从被消除状态出发的转换
        self_loop = self.transitions.get((state_to_eliminate, state_to_eliminate), 'ε')
        
        for state in self.states:
            if state != state_to_eliminate:
                in_trans = self.transitions.get((state, state_to_eliminate), '∅')
                if in_trans != '∅':
                    incoming.append((state, in_trans))
                
                out_trans = self.transitions.get((state_to_eliminate, state), '∅')
                if out_trans != '∅':
                    outgoing.append((state, out_trans))
        
        print(f"  进入转换: {
     
     incoming}")
        print(f"  自环: {
     
     self_loop}")
        print(f"  出发转换: {
     
     outgoing}")
        
        # 更新转换表
        new_tran
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值