构造LR(0)分析表和SLR(1)分析表

目录

1.构造LR(0)分析表

2.构造SLR(1)分析表

LR(0)和SLR(1)的联系


1.构造LR(0)分析表

构造LR(0)分析表的步骤如下:

拓广文法--->列项目--->项目集规范簇--->分析表

拓广文法是一种用于描述上下文无关文法的元语法表示法,通过引入了一些扩展的符号和表示方式,以使得语法的描述更加直观

看下面的拓广文法,这里的(0)E'-->E:表示通过E'指向开始文法

列项目:

①首先将每个产生式的右部加“点”

②将通过不同符号的类列举出来

③若列举出来的语句中“点”后面是非终结符,那么需要将该非终结符所属的类都写下来,除了E'->E 。例如 E-->"点"E+T,"点"后面是E,所以将 E->"点" E +T E-> "点" T 写下来,不写E'-->“点” E

接下来分析I0:

由于E'--->E"点"中的"点"已经到最后了,不需要进一步分析

同理可得:

分析表:

列出这样的表,0~8分别表示I0~I8:

第一行表示从I0出发,经过一个E,到达状态1,I0输入T,到达状态2,I0输入a,到达状态5,I0输入"(",到达状态3

以此类推:

若"点"已经在最后了, 表示这个项目已经结束,用”r“表示,在拓广文法中找到相同的项目,填入序号。例如这里的T2:E-->T,在拓广文法中对应(2)

最后,状态1包含"E'-->E",所以在状态1的“#”列表明all

2.构造SLR(1)分析表

SLR(1)步骤和LR(0)相同,只是多求了一部FOLLOW集

点在不同位置,代表的项目不同:

归约项目(A-->\alpha•):•在最后
移进项目(A-->\alpha•xB):•后面是终结符

接受项目(S--->\alpha•):开始文法对应的
待约项目(A--->\alpha•XB):•后面是是非终结符

来看以下例子:

通过DFA得到的表如下图所示,但是这里先不用填“r”,表示终结

接下来我们求非终结符的FOLLOW集合:

将Follow集的终结符,写在"r"的位置,例如,拓广文法中(2)E-->T,那么E的FOLLOW集={+,),#}

以此类推,得到:

SLR(1)的出现其实是为了解决LR(0)的两个矛盾,即同一个项目中会产生矛盾:移进---归约        归约---归约

(1)归约---归约

A--->a•

B--->a•

以上就出现了(归约---归约)错误,A的follow集/B的follow集不知是用"A--->a•"还是"B--->a•"

归约

(2)移进---归约(•后面是终结符---•在最后):

表中划圈部分满足,即I1和I3都存在移进---归约错误:

在I1中,我们将•后面的终结符“+”与该项目的开始符“ S’ ”的Follow集相交

I3同理:

得出的两个交集皆为\phi(空),那么说明LR(0)文法也满足SLR(1)文法的要求,是SLR(1)文法。

LR(0)和SLR(1)的联系

若不存在冲突项目,那么既是LR(0)文法,也是SLR(1)文法

若存在冲入项目,且满足Follow集为\phi(空)的条件,那么就是SLR(1)文法,如果也不满足那么就既不是LR(0)文法,也不是SLR(1)文法

也就是说SLR(0)包含不冲突的项目,也包含符合条件的冲突项目:

SLR(0)\supseteqLR(0)

  • 25
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用Java语言编写LR(0)分析构造的示例代码: ``` import java.util.*; public class LR0Parser { private Grammar grammar; // 存储文法的对象 private Map<String, Integer> nonTerminals; // 非终结符号的编号 private Map<String, Integer> terminals; // 终结符号的编号 private List<Set<Item>> canonicalCollection; // LR(0)自动机的状态集合 private int[][] actionTable; // 移进-规约 private int[][] gotoTable; // 转移 public LR0Parser(Grammar grammar) { this.grammar = grammar; this.nonTerminals = new HashMap<>(); this.terminals = new HashMap<>(); this.canonicalCollection = new ArrayList<>(); this.actionTable = null; this.gotoTable = null; } public void buildTables() { // 初始化非终结符号和终结符号的编号 int id = 0; for (String symbol : grammar.getSymbols()) { if (grammar.isNonTerminal(symbol)) { nonTerminals.put(symbol, id++); } else { terminals.put(symbol, id++); } } // 构造LR(0)自动机 canonicalCollection.add(closure(new HashSet<>(Collections.singletonList( new Item(grammar.getProduction(0), 0))))); int i = 0; while (i < canonicalCollection.size()) { Set<Item> itemSet = canonicalCollection.get(i++); for (String symbol : grammar.getSymbols()) { Set<Item> nextSet = gotoSet(itemSet, symbol); if (!nextSet.isEmpty() && !canonicalCollection.contains(nextSet)) { canonicalCollection.add(nextSet); } } } // 构造移进-规约和转移 actionTable = new int[canonicalCollection.size()][terminals.size()]; gotoTable = new int[canonicalCollection.size()][nonTerminals.size()]; for (i = 0; i < canonicalCollection.size(); i++) { Set<Item> itemSet = canonicalCollection.get(i); for (Item item : itemSet) { if (item.isReduceItem()) { Production production = item.getProduction(); int j = nonTerminals.get(production.getLeft()); if (actionTable[i][terminals.size() - 1] != 0) { throw new RuntimeException("LR(0)文法不是SLR文法"); } actionTable[i][terminals.size() - 1] = -production.getId() - 1; } else { String symbol = item.getSymbol(); int j = grammar.isNonTerminal(symbol) ? nonTerminals.get(symbol) : terminals.get(symbol); int k = canonicalCollection.indexOf(gotoSet(itemSet, symbol)); if (grammar.isNonTerminal(symbol)) { gotoTable[i][j] = k; } else { actionTable[i][j] = k; } } } } } public int parse(List<Token> tokens) { Stack<Integer> stateStack = new Stack<>(); // 状态栈 Stack<Integer> symbolStack = new Stack<>(); // 符号栈 stateStack.push(0); symbolStack.push(terminals.get("$")); for (Token token : tokens) { int state = stateStack.peek(); int symbol = token.getType(); int action = actionTable[state][symbol]; if (action > 0) { // 移进操作 stateStack.push(action); symbolStack.push(symbol); } else if (action < 0) { // 规约操作 Production production = grammar.getProduction(-action - 1); for (int i = 0; i < production.getRight().size(); i++) { stateStack.pop(); symbolStack.pop(); } int newState = gotoTable[stateStack.peek()][nonTerminals.get(production.getLeft())]; stateStack.push(newState); symbolStack.push(nonTerminals.get(production.getLeft())); } else { // 错误处理 throw new RuntimeException("语法错误"); } } return symbolStack.pop(); } // 计算项目集闭包 private Set<Item> closure(Set<Item> itemSet) { Queue<Item> queue = new LinkedList<>(itemSet); while (!queue.isEmpty()) { Item item = queue.poll(); if (!item.isReduceItem() && grammar.isNonTerminal(item.getSymbol())) { String symbol = item.getNextSymbol(); for (Production production : grammar.getProductions(symbol)) { Item newItem = new Item(production, 0); if (!itemSet.contains(newItem)) { itemSet.add(newItem); queue.offer(newItem); } } } } return itemSet; } // 计算项目集的转移 private Set<Item> gotoSet(Set<Item> itemSet, String symbol) { Set<Item> result = new HashSet<>(); for (Item item : itemSet) { if (!item.isReduceItem() && item.getSymbol().equals(symbol)) { result.add(new Item(item.getProduction(), item.getPosition() + 1)); } } return closure(result); } } ``` 注:上述代码中,`Grammar`是一个存储文法的对象,`Token`是一个存储词法分析结果的对象,`Item`是一个示项目的对象,`Production`是一个示产生式的对象。在实际使用中,需要根据具体的需求进行相应的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值