lr0分析程序的设计与实现
时间: 2024-06-18 14:02:44 浏览: 13
LR(0)分析程序是一种语法分析方法,它通过建立文法的DFA状态转移图,来确定输入的符号串是否可以被该文法所接受。LR(0)分析程序的设计与实现可以大致分为以下几个步骤:
1. 文法预处理:将输入的文法转换为一些易于处理的形式。比如,将文法转换为扩充文法、消除左递归、消除公共左因子等。
2. 构造项集:根据扩充文法,构建出LR(0)项集族。一个项集包含了一些项,每个项表示了一条可能的规约或移进的路径。
3. 构造DFA:基于项集族构建出DFA状态转移图。DFA中的每个状态都是由一个项集生成的,每个转移条件都是由一个文法符号生成的。
4. 构造分析表:对于DFA中的每个状态,构造出对应的分析表,其中包含了移进、规约以及错误处理等操作。这些操作根据当前状态和下一个输入符号来进行。
5. 解析过程:利用构造好的分析表,解析输入的符号串,得到最终的分析结果。如果输入符号串可以被该文法所接受,则输出“accept”;否则输出“error”。
相关问题
LR0分析程序的设计与实现代码
以下是一个简单的 LR(0) 分析程序的设计与实现代码,用 Python 语言实现:
```python
# LR(0) 分析程序
# 标识符常量
SHIFT = 1
REDUCE = 2
ACCEPT = 3
ERROR = 4
# 产生式类
class Production:
def __init__(self, head, body):
self.head = head
self.body = body
# 项目类
class Item:
def __init__(self, production, dot):
self.production = production
self.dot = dot
def __eq__(self, other):
return self.production == other.production and self.dot == other.dot
def __hash__(self):
return hash(str(self.production) + str(self.dot))
# LR(0) 分析表类
class LR0Table:
def __init__(self, grammar):
self.grammar = grammar
self.actions = {}
self.gotos = {}
# 构造项目集规范族
self.canonical_collection = self.build_canonical_collection()
# 构造 LR(0) 分析表
self.build_table()
# 构造项目集规范族
def build_canonical_collection(self):
# 第一步:初始化
start_production = self.grammar.productions[0]
start_item = Item(start_production, 0)
closure = self.closure(set([start_item]))
current_state = frozenset(closure)
canonical_collection = {current_state: closure}
# 第二步:循环直到项目集规范族没有变化
while True:
for item in current_state:
# 对于每个项目 A -> α·Bβ,进行 GOTO 操作
if not item.dot == len(item.production.body):
symbol = item.production.body[item.dot]
goto = self.goto(current_state, symbol)
if not goto in canonical_collection:
closure = self.closure(goto)
canonical_collection[goto] = closure
# 如果项目集规范族没有变化,则退出循环
if len(canonical_collection) == len(current_state):
break
else:
current_state = list(canonical_collection.keys())[-1]
return canonical_collection
# 求闭包
def closure(self, items):
closure = set(items)
while True:
new_items = set()
for item in closure:
# 对于每个项目 A -> α·Bβ,将 B -> γ 加入 new_items
if not item.dot == len(item.production.body):
symbol = item.production.body[item.dot]
if symbol in self.grammar.non_terminals:
for production in self.grammar.productions:
if production.head == symbol:
new_item = Item(production, 0)
if not new_item in closure:
new_items.add(new_item)
if not new_items:
break
closure |= new_items
return closure
# 求 GOTO(A -> α·Bβ, b)
def goto(self, items, symbol):
goto = set()
for item in items:
if not item.dot == len(item.production.body) and item.production.body[item.dot] == symbol:
goto.add(Item(item.production, item.dot + 1))
return frozenset(self.closure(goto))
# 构造 LR(0) 分析表
def build_table(self):
for i, state in enumerate(self.canonical_collection):
# 对于每个项目 A -> α·,将 ACTION[s, a] 设为 SHIFT(t),其中 t = GOTO[s, a]
for item in state:
if item.dot == len(item.production.body):
if item.production.head == self.grammar.start_symbol:
self.actions[(i, '$')] = (ACCEPT, None)
else:
for symbol in self.grammar.follow(item.production.head):
self.actions[(i, symbol)] = (REDUCE, item.production)
else:
symbol = item.production.body[item.dot]
goto = self.goto(state, symbol)
if symbol in self.grammar.terminals:
self.actions[(i, symbol)] = (SHIFT, goto)
else:
self.gotos[(i, symbol)] = goto
# 执行 LR(0) 分析
def parse(self, input):
stack = [0]
output = []
while True:
state = stack[-1]
symbol = input[0]
if (state, symbol) in self.actions:
action, arg = self.actions[(state, symbol)]
if action == SHIFT:
stack.append(arg)
input = input[1:]
elif action == REDUCE:
head = arg.head
body = arg.body
output.append(arg)
for i in range(len(body)):
stack.pop()
state = stack[-1]
stack.append(self.gotos[(state, head)])
elif action == ACCEPT:
output.append(arg)
return output
else:
raise Exception('Syntax error')
else:
raise Exception('Syntax error')
```
此代码实现了 LR(0) 分析程序的主要功能,包括构造项目集规范族、构造 LR(0) 分析表和执行 LR(0) 分析。使用时需要提供一个文法对象(包括产生式和起始符号)和一个输入串。输出为分析树或语法错误。
LR0分析程序的设计与实现代码,使用C语言
以下是一个简单的LR(0)分析程序的设计和实现代码,使用了C语言:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STATES 100
#define MAX_SYMBOLS 100
#define MAX_PRODUCTIONS 100
// 定义文法
char *grammar[] = {
"S->E",
"E->E+T",
"E->T",
"T->T*F",
"T->F",
"F->(E)",
"F->id"
};
int num_symbols = 5;
// 定义项目
char *closure(char **I, int n) {
char **J = I;
int m = n;
while (1) {
int item_added = 0;
for (int i = 0; i < m; i++) {
char *item = J[i];
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
continue;
}
char next_symbol = item[dot_pos + 1];
if (next_symbol >= 'A' && next_symbol <= 'Z') {
for (int j = 0; j < num_symbols; j++) {
if (grammar[j][0] == next_symbol) {
char *new_item = malloc(strlen(grammar[j]) + 4);
sprintf(new_item, "%c->.%s", next_symbol, grammar[j] + 3);
if (!strstr(J[0], new_item) && !strstr(J[m-1], new_item)) {
J[m++] = new_item;
item_added = 1;
} else {
free(new_item);
}
}
}
}
}
if (!item_added) {
break;
}
}
char *closure = malloc(m * (strlen(grammar[0]) + 1));
strcpy(closure, J[0]);
for (int i = 1; i < m; i++) {
strcat(closure, "/");
strcat(closure, J[i]);
}
return closure;
}
// 定义goto函数
int goto(char **I, int n, char X, char **J) {
int m = 0;
for (int i = 0; i < n; i++) {
char *item = I[i];
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
continue;
}
char next_symbol = item[dot_pos + 1];
if (next_symbol == X) {
char *new_item = malloc(strlen(item) + 1);
strcpy(new_item, item);
new_item[dot_pos] = next_symbol;
new_item[dot_pos + 1] = '.';
J[m++] = new_item;
}
}
char *closure_J = closure(J, m);
int ret = 1;
for (int i = 0; i < n; i++) {
if (strcmp(I[i], closure_J) == 0) {
ret = 0;
break;
}
}
if (ret) {
strcpy(I[n], closure_J);
}
free(closure_J);
return ret ? n + 1 : -1;
}
// 构造LR(0)自动机
char *states[MAX_STATES];
int num_states = 1;
char *queue[MAX_STATES];
void construct_LR0_automaton() {
char *C = closure((char *[]){"S->.E"}, 1);
states[0] = C;
queue[0] = C;
int head = 0, tail = 1;
while (head < tail) {
C = queue[head++];
for (char symbol = 'A'; symbol <= 'Z'; symbol++) {
char *J[MAX_PRODUCTIONS];
int m = goto(C, strlen(C), symbol, J);
if (m > 0) {
states[num_states] = J[0];
for (int i = 1; i < m; i++) {
strcat(states[num_states], "/");
strcat(states[num_states], J[i]);
}
queue[tail++] = states[num_states];
num_states++;
}
}
}
}
// 定义LR(0)分析表
enum Action {
SHIFT,
REDUCE,
ACCEPT
};
struct TableEntry {
enum Action action;
int num;
};
struct TableEntry action[MAX_STATES][MAX_SYMBOLS];
int goto_table[MAX_STATES][MAX_SYMBOLS];
void construct_LR0_table() {
for (int i = 0; i < num_states; i++) {
for (int j = 0; j < MAX_SYMBOLS; j++) {
action[i][j].action = -1;
goto_table[i][j] = -1;
}
}
for (int i = 0; i < num_states; i++) {
char *C = states[i];
char *item = strtok(C, "/");
while (item) {
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
for (int j = 0; j < num_symbols; j++) {
if (grammar[j][0] == item[0]) {
action[i]['$' - 'A'].action = ACCEPT;
action[i]['$' - 'A'].num = j;
break;
}
}
} else {
char X = item[dot_pos + 1];
if (X >= 'a' && X <= 'z') {
action[i][X - 'A'].action = SHIFT;
action[i][X - 'A'].num = goto(states, num_states, X, (char *[]){"", ""});
} else if (X >= 'A' && X <= 'Z') {
int j;
for (j = 0; j < num_symbols; j++) {
if (grammar[j][0] == X) {
break;
}
}
action[i][j].action = REDUCE;
action[i][j].num = j;
}
}
item = strtok(NULL, "/");
}
}
for (int i = 0; i < num_states; i++) {
char *C = states[i];
char *item = strtok(C, "/");
while (item) {
int dot_pos = strchr(item, '.') - item;
if (dot_pos < strlen(item) - 1) {
char X = item[dot_pos + 1];
if (X >= 'A' && X <= 'Z') {
goto_table[i][X - 'A'] = goto(states, num_states, X, (char *[]){"", ""});
}
}
item = strtok(NULL, "/");
}
}
}
// 测试
int parse_LR0(char *string) {
int stack[MAX_STATES];
int top = 0;
stack[top++] = 0;
char *input_str = malloc(strlen(string) + 2);
strcpy(input_str, string);
strcat(input_str, "$");
int output[MAX_PRODUCTIONS];
int num_output = 0;
while (1) {
int state = stack[top - 1];
char a = input_str[0];
if (action[state][a - 'A'].action == -1) {
printf("error\n");
return -1;
}
switch (action[state][a - 'A'].action) {
case SHIFT:
stack[top++] = action[state][a - 'A'].num;
input_str++;
break;
case REDUCE: {
int num = action[state][a - 'A'].num;
output[num_output++] = num;
char *production = grammar[num];
int len = strlen(production) - 3;
for (int i = 0; i < len * 2; i++) {
top--;
}
state = stack[top - 1];
stack[top++] = goto_table[state][production[0] - 'A'];
break;
}
case ACCEPT:
output[num_output++] = num_symbols;
for (int i = 0; i < num_output; i++) {
printf("%s\n", grammar[output[i]]);
}
return 0;
}
}
}
int main() {
construct_LR0_automaton();
construct_LR0_table();
parse_LR0("id+id*id");
return 0;
}
```
这段代码实现了一个简单的LR(0)分析程序,包括构造LR(0)自动机和分析表,以及使用分析表进行语法分析的过程。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![-](https://csdnimg.cn/download_wenku/file_type_lunwen.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![-](https://csdnimg.cn/download_wenku/file_type_column_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)