first集follow集怎么求
时间: 2023-10-19 22:42:26 浏览: 90
First集和Follow集是语法分析中的概念,是用于判断一个文法是否为LL(1)文法的重要工具。
First集是指一个非终结符号能推导出的所有符号的首字母集合。
Follow集是指在文法中,在一个非终结符号之后的符号集合。
对于C语言来说,要计算First集和Follow集,需要对C语言的语法进行分析,计算每一个非终结符号的First集和Follow集。
相关问题
first集follow集
### 关于First集和Follow集的概念
在编译原理中,`FIRST` 集合用于表示某个符号串可能开始的终结符集合;如果该符号串可以推出空字符串,则 `ε` 属于其 `FIRST` 集合[^2]。对于非终结符而言,`FOLLOW` 集合则定义为其后续可能出现的所有终结符以及句末标记 `$` 的集合。
具体来说:
- **FIRST(T)** 表示由 T 所代表的符号序列能够推导出来的第一个字符组成的集合;
- 如果 T 能够推导出 ε (即空),那么 FIRST(T) 中也包含 ε;
- 对于任意文法 G 和其中任何符号 X ∈ V∪T,有如下规则来构建 FIRST(X):
- 若 X 是终结符,则 FIRST(X)={X};
- 若 X 是非终结符且存在产生式 X → ε ,则将 ε 加入到 FIRST(X) 中;
- 对于形如 X → Y1Y2...Yk 的产生式,当 i=1 到 k−1 时,若 Yi 可以全部被替换为空串,则应把除 Yi 外其他所有元素对应的 FIRST(Yj)(不含 ε )加入至 FIRST(X) 内,并最终考虑是否要加上 ε。
针对 Follow 集合:
- FOLLOW(S) 总会含有结束标志 $ (假设 S 是起始符号),因为程序执行完毕意味着遇到了文件结尾;
- 当 B 出现在 A -> αBβ 形式的右侧位置上时,所有的 FIRST(β)\{ε\} 应该加进 FOLLOW(B) 里去;
- 如果 β 可能为 ε 或者更进一步地讲,在某些情况下整个右边部分都可以变成 ε,此时还需要将 FOLLOW(A) 添加到 FOLLOW(B) 中[^4]。
### First集和Follow集的计算方法
为了更好地理解如何实际操作这些理论上的概念,下面给出具体的 Python 实现例子来进行说明:
#### 计算 FIRST 集合
```python
def compute_first(grammar, symbol):
first_set = set()
if is_terminal(symbol): # 终结符直接返回自己
return {symbol}
for production in grammar[symbol]:
for sym in production.split():
f = compute_first(grammar, sym)
if 'ε' not in f:
first_set |= f
break
elif len(f) > 0 and 'ε' in f:
first_set |= f.difference({'ε'})
else: # 如果循环正常退出(未遇到非空)
first_set.add('ε')
return first_set
```
#### 计算 FOLLOW 集合
```python
from collections import defaultdict
def initialize_follow_sets(start_symbol):
follows = defaultdict(set)
follows[start_symbol].add('$') # 开始符号后面跟$
return follows
def update_follows_with_production(follows, lhs, rhs):
n = len(rhs)
for idx, current_sym in enumerate(rhs):
next_syms = rhs[idx + 1:]
if is_nonterminal(current_sym):
temp_follow = set()
for nxt in next_syms:
if is_terminal(nxt):
temp_follow.add(nxt)
break
elif is_nonterminal(nxt):
temp_follow.update(compute_first(grammar, nxt).difference({'ε'}))
if 'ε' not in compute_first(grammar, nxt):
break
else: # 正常遍历完next_symbols
if idx == n - 1 or any(['ε' in compute_first(grammar, s) for s in next_syms]):
temp_follow.update(follows[lhs])
follows[current_sym].update(temp_follow)
return follows
```
上述代码片段展示了基于给定文法规则动态更新 `FOLLOW` 集的方法之一。这里假设有辅助函数 `is_terminal()` 和 `is_nonterminal()` 来判断一个符号是不是终结符或非终结符,还有之前提到过的 `compute_first()` 方法用来获取特定符号的第一个符号集合。
c语言代码实现求first集follow集select集
在编译原理中,First集、Follow集和Select集是用于描述文法分析中的关键概念。这里简述它们的含义:
1. **First集**:First集合表示给定一个非终结符或 terminals (终结符) ,所有出现在它直接右部的字符串的第一个字符组成的集合。例如,如果有一个非终结符A,其产生式是A -> aB | bC,那么A的第一集就是{a}。
```c
typedef struct {
int symbol;
char* first_set[26]; // 假设我们用小写字母作为字符集,大小是26
} FirstTable;
void compute_first_set(FirstTable* table, const Grammar* grammar) {
for (/* each production rule */)
compute_first_of_production(table, grammar);
}
```
2. **Follow集**:Follow集是针对文法中的某个符号,紧跟在其后的最右边的终结符集合。Follow(A) 包含 A->*的所有可能终结符序列中的最后一个字符,对于文法来说,这有助于确定何时结束识别过程。
```c
typedef struct {
char* follow_set[26];
} FollowTable;
void compute_follow_set(FollowTable* table, const Grammar* grammar) {
for (/* each production rule */)
compute_follow_of_production(table, grammar);
}
```
3. **Select集**:Select集在LR分析中特别重要,它是Follow集的一种特殊形式,只包含那些在shift-reduce冲突解决中需要的终结符,即那些在状态机的reduce动作之后可以直接读取的终结符。
```c
typedef struct {
char* select_set[26];
} SelectTable;
void compute_select_set(SelectTable* table, const FollowTable& follow_table, const Grammar* grammar) {
for (/* each state in LR parsing table */)
compute_select_in_state(table, follow_table, grammar);
}
```
实现这些集合通常会涉及到遍历文法规则,并基于上下文无关文法的性质来填充表。以上代码片段仅提供了一个基本的框架,实际实现可能会更复杂,需要考虑更多的细节,如处理左递归等特殊情况。
阅读全文
相关推荐











