构造LR(0)分析表

1.什么叫LR(0)文法

假若一个文法G的拓广文法G'的活前缀识别自动机中的每个状态(项目集)不存在下述情况︰

(1)既含移进项目又含归约项目;

(2)含有多个归约项目;

则称G是一个LR(0)文法。

2.如何构造LR(0)分析表

(1)令每个项目集I的下标k作为分析器的状态,包含项目S'→·S的集合I的下标k为分析器的初态。

(2)构造LR(O)分析表的ACTION和GOTO子表 

3.LR(0)分析表的ACTION和GOTO子表构造

4.例题分析

 

(1)状态0

对于状态0而言我们可以看到有通过终结符a到达状态2 ,因为a为终结符,到达的状态2这个操作应该填在ACTION表中,在相应位置填上s2,表示将2移进。同理状态0也可以通过b到达状态3,将s3填入对应位置。

 

我们接着分析状态0,还可以发现状态0可以通过E到达状态1,因为E为非终结符,此时做的一定是规约操作,对照推导式我们可以发现可以规约第一个推导式E->aA得到,故将1填到GOTO表的对应位置。

 (2)状态1

状态1对照表格发现只有一个接受状态,所以在1这一行的#这一列填上acc。

 

(3)状态2

(4)状态3

 

(5)状态4

 

(6)状态5

状态6告诉你要规约,用的是第1的推导式E->aA做规约,所以不管是状态a,b,c,d,#,都对其做规约。

 

(7) 结果

 

 

 

  • 30
    点赞
  • 194
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
由于LR(0)分析是基于DFA(确定有限状态自动机)的,因此我们需要先构造DFA,然后根据DFA构造LR(0)分析。下面是一个简单的Java代码示例,用于构造LR(0)分析。 首先,我们定义一个类来示DFA的状态: ``` class DFAState { int id; // 状态ID Set<Integer> items; // LR(0)项目集合 // 构造函数 public DFAState(int id, Set<Integer> items) { this.id = id; this.items = items; } // 判断两个状态是否相同 public boolean equals(Object obj) { if (obj instanceof DFAState) { DFAState other = (DFAState) obj; return this.id == other.id && this.items.equals(other.items); } return false; } // 计算状态的哈希值 public int hashCode() { return id * 31 + items.hashCode(); } } ``` 接下来,我们定义一个LR(0)分析类: ``` class LR0Table { int[][] action; // 移进-规约 int[][] goTo; // 转移 // 构造函数 public LR0Table(int numStates, int numSymbols) { this.action = new int[numStates][numSymbols]; this.goTo = new int[numStates][numSymbols]; } // 设置移进-规约的值 public void setAction(int state, int symbol, int value) { this.action[state][symbol] = value; } // 设置转移的值 public void setGoTo(int state, int symbol, int value) { this.goTo[state][symbol] = value; } // 获取移进-规约的值 public int getAction(int state, int symbol) { return this.action[state][symbol]; } // 获取转移的值 public int getGoTo(int state, int symbol) { return this.goTo[state][symbol]; } } ``` 然后,我们定义一个LR(0)分析器类,它包含了构造LR(0)分析的所有方法: ``` class LR0Parser { Grammar grammar; // 文法 LR0Table table; // LR(0)分析 // 构造函数 public LR0Parser(Grammar grammar) { this.grammar = grammar; this.table = new LR0Table(grammar.numStates(), grammar.numSymbols()); } // 构造DFA private Map<DFAState, Map<Integer, DFAState>> constructDFA() { // TODO: 构造DFA } // 构造LR(0)分析 public void constructTable() { Map<DFAState, Map<Integer, DFAState>> dfa = constructDFA(); // 构造移进-规约 for (DFAState state : dfa.keySet()) { for (int symbol : grammar.symbols()) { DFAState nextState = dfa.get(state).get(symbol); if (nextState != null) { // 移进 if (grammar.isTerminal(symbol)) { table.setAction(state.id, symbol, nextState.id); } // 转移 else { table.setGoTo(state.id, symbol, nextState.id); } } } // 规约 for (int item : state.items) { if (grammar.isReduceItem(item)) { int symbol = grammar.reduceSymbol(item); for (int t : grammar.follow(symbol)) { table.setAction(state.id, t, -item); } } } } } // 获取LR(0)分析 public LR0Table getTable() { return this.table; } } ``` 在上面的代码中,我们首先定义了一个`constructDFA()`方法,用于构造DFA。然后,在`constructTable()`方法中,我们根据DFA构造移进-规约和转移。最后,我们定义了一个`getTable()`方法,用于获取LR(0)分析。 最后,我们可以使用以下代码来测试LR(0)分析构造: ``` public static void main(String[] args) { String[] productions = { "S -> E", "E -> E + T", "E -> T", "T -> T * F", "T -> F", "F -> ( E )", "F -> id" }; Grammar grammar = new Grammar(productions); LR0Parser parser = new LR0Parser(grammar); parser.constructTable(); LR0Table table = parser.getTable(); // TODO: 使用LR(0)分析进行语法分析 } ``` 注意,上面的代码中,我们使用了一个`Grammar`类来示文法,并且假设文法的起始符号为S。`Grammar`类的实现可以参考我们之前的文章。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值