SLR(1)分析文法:E->E+T|T,T->T*F|F,F->(E)|d 及其代码实现
SLR(1)分析文法:E->E+T|T,T->T*F|F,F->(E)|d 及其代码实现
文法介绍
本例分析的文法如下:
E -> E + T | TT -> T * F | FF -> ( E ) | d
该文法描述了一个简单的算术表达式,其中:
- E 表示表达式* T 表示项* F 表示因子* + 表示加法运算* * 表示乘法运算* ( ) 表示括号* d 表示一个数字
SLR(1)分析
SLR(1)分析是一种自底向上的语法分析方法,它使用一个分析表来指导分析过程。分析表包含了在当前状态下,遇到某个输入符号时应该采取的动作,例如移进、归约或报错。
构建 SLR(1) 分析表
-
构造文法的增广文法:
S' -> E E -> E + T | T T -> T * F | F F -> ( E ) | d -
计算 FIRST 集和 FOLLOW 集
- FIRST(E) = { ( , d } * FIRST(T) = { ( , d } * FIRST(F) = { ( , d } * FOLLOW(E) = { # , ) , + } * FOLLOW(T) = { # , ) , + , * } * FOLLOW(F) = { # , ) , + , * }
-
构造 LR(0) 项目集规范族: * 根据增广文法,从初始项目 S' -> .E 开始,逐步推导,构建 LR(0) 项目集规范族。
-
构造 SLR(1) 分析表: * 根据 LR(0) 项目集规范族和 FOLLOW 集,构建 SLR(1) 分析表。
分析过程
- 初始化: 将初始状态 0 压入状态栈,将 # 压入符号栈,将输入串和 # 拼接后作为输入。2. 循环执行以下步骤,直到状态栈为空或者遇到错误: * 获取当前状态栈顶的状态和当前输入符号。 * 根据分析表查找对应的动作。 * 执行动作: * 移进: 将当前输入符号压入符号栈,将下一状态压入状态栈,并将输入指针指向下一个输入符号。 * 归约: 根据分析表中的产生式进行归约,将符号栈和状态栈弹出相应数量的元素,并将归约后的非终结符压入符号栈,根据 GOTO 表查找下一状态并压入状态栈。 * 接受: 分析成功。 * 报错: 分析失败。
代码实现
以下是使用 Java 实现的 SLR(1) 分析器代码:javaimport java.util.*;
public class SLR1Parser {
// ... (其他代码与题目中提供的一致)
public List<char> GetFollow(char c) { List<char> follow = new List<char>(); if (c == 'E') follow.Add('#'); foreach (SLRNode node in SLRproNum) { int index = node.Right.IndexOf(c); if (index != -1 && index < node.Right.Length - 1) { char next = node.Right[index + 1]; if (isFinalsymbol(next)) follow.Add(next); else { List<char> first = GetFirst(next); if (first.Contains('#')) { first.Remove('#'); follow.AddRange(first); // 修正:递归获取下一个符号的 FOLLOW 集 List<char> nextFollow = GetFollow(node.Left[0]); follow.AddRange(nextFollow); } else { follow.AddRange(first); } } } else if (index != -1 && index == node.Right.Length - 1) { // 修正:递归获取产生式左部非终结符的 FOLLOW 集 List<char> nextFollow = GetFollow(node.Left[0]); follow.AddRange(nextFollow); } } follow = follow.Distinct().ToList(); return follow; }
// ... (其他代码与题目中提供的一致
原文地址: https://www.cveoy.top/t/topic/f0JM 著作权归作者所有。请勿转载和采集!