右线性文法转到左线性文法

首先简单介绍一下右线性文法和左线性文法:

上图是一个DFA(确定有限自动机),a是初始状态,f是终止状态。

文法中的“|”可以理解为“或者”。

对应的右线性文法:
A->0|0B|1D(A->0意思是A状态接收0到达终态,由于终态f没有转出,这时候终态f不需要写出来)

B->0D|1C(B->0D意思是B状态接收0到达D状态)

C->0|0B|1D(C->0意思是到达终态,终态f没有转出,不需要再写出来)

D->0D|1D(D->0D意思是D状态接收0到达D状态,就是到达自身)

右线性文法一般的规则:A->0B,A接收0到达B。当A状态接收1到达终态的时候,如果终态只是单纯的终点,没有转出状态,可以写成A->1,终态不用写。

对应的左线性文法:

B->C0|0(B->C0:B状态是C状态接收0得到的;B->0:B状态是初始状态接收0得到的,由于初始状态A没有转入,只有转出,所以可以不写)

C->B1(C状态是B状态接收1得到的)

D->D0|D1|C1|B0|1(D->0意思是D是初态接收0得到的,由于初态只是单纯的起始点,不用写出来)

左线性文法一般的规则:A->B0,B接收0到达A,A是B接收0得到的。当初始状态接收1到达A状态的时候,如果初始状态只是单纯的起点,没有转入状态,可以写成A->1,初始状态不用写。

当需要左右文法转换的时候,往往借助中间的图形进行过渡。

以一个题目来说明:(编译原理课本课后题,P65 15题)

给定右线性文法G:

S -> 0S | 1S | 1A | 0B

A -> 1C | 1

B -> 0C | 0

C -> 0C | 1C | 0 | 1

求一个与G等价的左线性文法。

首先根据右线性文法,画出状态转移图:
如下图,这是一个NFA(非确定的有限自动机):

这里,S是起始状态,但是不是单纯的起点,它接收0或者1能够到达S状态。F是终止状态,是单纯的终点。

根据图,可以写出对应的左线性文法:
F->A1|B0|C0|C1

C->A1|B0|C0|C1

B->S0(B是初始状态S接收0得到的,但是初始状态S并不是单纯的起点,它是状态S接收0/1得到的,所以需要写出来,如果写成B->0,是不对的,表达的不是一个意思,初始状态和终止状态写出来还是不写出来是严格确定的,如果写错,代表的是不同的自动机。)

A->S1

S->S0|S1

左右文法的转换是大差不差的,都可以这么做,只不过要特别注意起始状态和终止状态

### 关于右线性文法 #### 定义 右线性文法是一种特殊的上下文无关文法(CFG),其生产规则的形式满足以下条件之一: - \( A \rightarrow wB \),其中 \( A, B \) 是非终结符,\( w \) 是由终结符组成的字符串。 - \( A \rightarrow w \),其中 \( A \) 是非终结符,\( w \) 是由终结符组成的字符串。 这种形式的特点是非终结符始终位于侧表达式的最边位置[^1]。 #### 示例 以下是右线性文法的一个简单例子: 假设有一个语言 \( L = \{a^n b | n \geq 0\} \),对应的右线性文法可以表示如下: - 非终结符集合:\( S, A \) - 终结符集合:\( a, b \) 文法规则为: ```plaintext S → Ab A → ε A → aA ``` 解释: - \( S \rightarrow Ab \) 表示从起始符号 \( S \) 开始生成以 \( b \) 结尾的字符串。 - \( A \rightarrow \varepsilon \) 和 \( A \rightarrow aA \) 则分别负责生成零个或多个 \( a \)[^3]。 #### 使用场景 右线性文法主要用于描述正则语言。它在实际应用中有以下几个重要领域: 1. **词法分析器的设计** 编译器中的词法分析阶段通常会利用有限状态自动机来识别单词模式,而这些模式可以用右线性文法描述并转换成相应的 DFA 或 NFA 进行匹配[^2]。 2. **建模简单的语法结构** 对于只需要捕获基本序列关系的语言部分,比如标识符、关键字或者数字格式等,可以直接采用右线性文法进行定义。 3. **简化复杂文法** 当构建更复杂的 CFG 文法时,某些子模块可能通过引入线性片段得以清晰化和优化[^3]。 ```python # Python 实现一个基于右线性文法的简单解析函数 def parse_right_linear(input_string): grammar_rules = { 'S': ['Ab'], 'A': ['', 'aA'] # '' represents epsilon/empty string } current_symbol = 'S' parsed_result = [] while input_string and current_symbol != '': matched_rule = False for rule in grammar_rules[current_symbol]: if not rule or (rule[0].isalpha() and input_string.startswith(rule[0])): if rule == 'b' and input_string[0] == 'b': parsed_result.append('b') input_string = input_string[1:] elif rule.startswith('a'): parsed_result.append('a') input_string = input_string[1:] next_non_terminal = '' if len(rule) > 1: next_non_terminal = rule[-1] current_symbol = next_non_terminal matched_rule = True break if not matched_rule: return "Invalid String" return ''.join(parsed_result) print(parse_right_linear("aab")) # 输出应为 "aab" 如果输入有效 ``` 上述代码展示如何依据给定的右线性文法对特定类型的字符串进行验证与解析。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值