实现LR(1)分析法的java代码

时间: 2023-08-20 17:04:11 浏览: 47
以下是一个简单的LR(1)分析器的Java代码,用于分析输入的字符串是否符合给定文法的规则: ```java import java.util.*; public class LR1Parser { private Map<Integer, Map<String, Action>> actionTable; private Map<Integer, Map<String, Integer>> gotoTable; private Map<Integer, Set<Item>> itemSets; private Map<String, Set<Integer>> followSets; private int startState; private String startSymbol; public LR1Parser(Grammar grammar) { // 构建LR(1)项集族 itemSets = buildItemSets(grammar); // 构建LR(1)分析表 actionTable = buildActionTable(grammar, itemSets); gotoTable = buildGotoTable(grammar, itemSets); // 计算起始状态和起始符号 startState = findStartState(itemSets, grammar.getStartSymbol()); startSymbol = grammar.getStartSymbol(); // 计算Follow集合 followSets = calculateFollowSets(grammar); } public boolean parse(String input) { // 初始化状态栈和符号栈 Stack<Integer> stateStack = new Stack<>(); Stack<String> symbolStack = new Stack<>(); stateStack.push(startState); symbolStack.push("$"); // 将输入符号串转换为Token序列 List<Token> tokens = scan(input); tokens.add(new Token("$", "")); // 开始语法分析 int i = 0; while (i < tokens.size()) { int state = stateStack.peek(); String symbol = tokens.get(i).getSymbol(); if (actionTable.containsKey(state) && actionTable.get(state).containsKey(symbol)) { // 查找分析表并执行对应动作 Action action = actionTable.get(state).get(symbol); if (action.getType() == Action.SHIFT) { stateStack.push(action.getValue()); symbolStack.push(symbol); i++; } else if (action.getType() == Action.REDUCE) { Production production = action.getProduction(); int numPops = production.getRight().size(); for (int j = 0; j < numPops; j++) { stateStack.pop(); symbolStack.pop(); } String nonterminal = production.getLeft(); int newState = gotoTable.get(stateStack.peek()).get(nonterminal); stateStack.push(newState); symbolStack.push(nonterminal); } else if (action.getType() == Action.ACCEPT) { return true; } else { return false; } } else { return false; } } return false; } private List<Token> scan(String input) { // 将输入符号串转换为Token序列 List<Token> tokens = new ArrayList<>(); String[] parts = input.split(" "); for (String part : parts) { String[] pair = part.split(":"); tokens.add(new Token(pair[0], pair[1])); } return tokens; } private Map<String, Set<Integer>> calculateFollowSets(Grammar grammar) { // 计算Follow集合 Map<String, Set<Integer>> followSets = new HashMap<>(); for (String nonterminal : grammar.getNonterminals()) { followSets.put(nonterminal, new HashSet<>()); } followSets.get(startSymbol).add(Grammar.EOF); boolean changed = true; while (changed) { changed = false; for (Production production : grammar.getProductions()) { String left = production.getLeft(); List<String> right = production.getRight(); for (int i = right.size() - 1; i >= 0; i--) { String symbol = right.get(i); if (grammar.isNonterminal(symbol)) { Set<Integer> follow = followSets.get(symbol); Set<Integer> first = calculateFirstSet(right.subList(i + 1, right.size()), grammar); int oldSize = follow.size(); follow.addAll(first); if (first.contains(Grammar.EMPTY) || i == right.size() - 1) { follow.addAll(followSets.get(left)); } if (follow.size() != oldSize) { changed = true; } } } } } return followSets; } private Set<Integer> calculateFirstSet(List<String> symbols, Grammar grammar) { // 计算给定符号串的First集合 Set<Integer> first = new HashSet<>(); boolean hasEmpty = true; for (String symbol : symbols) { Set<Integer> symbolFirst = grammar.getFirstSet(symbol); first.addAll(symbolFirst); if (!symbolFirst.contains(Grammar.EMPTY)) { hasEmpty = false; break; } } if (hasEmpty) { first.add(Grammar.EMPTY); } return first; } private int findStartState(Map<Integer, Set<Item>> itemSets, String startSymbol) { // 查找起始状态 for (Map.Entry<Integer, Set<Item>> entry : itemSets.entrySet()) { int state = entry.getKey(); Set<Item> items = entry.getValue(); for (Item item : items) { if (item.getDotPosition() == 0 && item.getProduction().getLeft().equals(startSymbol)) { return state; } } } return -1; } private Map<Integer, Map<String, Action>> buildActionTable(Grammar grammar, Map<Integer, Set<Item>> itemSets) { // 构建LR(1)分析表中的Action部分 Map<Integer, Map<String, Action>> actionTable = new HashMap<>(); for (Map.Entry<Integer, Set<Item>> entry : itemSets.entrySet()) { int state = entry.getKey(); Set<Item> items = entry.getValue(); Map<String, Action> actions = new HashMap<>(); for (Item item : items) { if (item.getDotPosition() == item.getProduction().getRight().size()) { if (item.getProduction().getLeft().equals(grammar.getStartSymbol())) { actions.put("$", new Action(Action.ACCEPT, -1, null)); } else { Set<Integer> follow = followSets.get(item.getProduction().getLeft()); for (int symbol : follow) { actions.put(grammar.getSymbolString(symbol), new Action(Action.REDUCE, item.getProduction().getIndex(), item.getProduction())); } } } else { String nextSymbol = item.getNextSymbol(); if (grammar.isTerminal(nextSymbol)) { int nextState = findNextState(itemSets, items, nextSymbol); actions.put(nextSymbol, new Action(Action.SHIFT, nextState, null)); } } } actionTable.put(state, actions); } return actionTable; } private Map<Integer, Map<String, Integer>> buildGotoTable(Grammar grammar, Map<Integer, Set<Item>> itemSets) { // 构建LR(1)分析表中的Goto部分 Map<Integer, Map<String, Integer>> gotoTable = new HashMap<>(); for (Map.Entry<Integer, Set<Item>> entry : itemSets.entrySet()) { int state = entry.getKey(); Set<Item> items = entry.getValue(); Map<String, Integer> gotos = new HashMap<>(); for (Item item : items) { if (item.getDotPosition() < item.getProduction().getRight().size()) { String nextSymbol = item.getNextSymbol(); if (grammar.isNonterminal(nextSymbol)) { int nextState = findNextState(itemSets, items, nextSymbol); gotos.put(nextSymbol, nextState); } } } gotoTable.put(state, gotos); } return gotoTable; } private int findNextState(Map<Integer, Set<Item>> itemSets, Set<Item> items, String symbol) { // 查找给定状态集合和符号的下一个状态 Set<Item> nextItems = new HashSet<>(); for (Item item : items) { if (item.getDotPosition() < item.getProduction().getRight().size() && item.getNextSymbol().equals(symbol)) { nextItems.add(new Item(item.getProduction(), item.getDotPosition() + 1, item.getLookahead())); } } return findItemSetState(itemSets, nextItems); } private int findItemSetState(Map<Integer, Set<Item>> itemSets, Set<Item> items) { // 查找给定LR(1)项集在LR(1)项集族中的状态 for (Map.Entry<Integer, Set<Item>> entry : itemSets.entrySet()) { int state = entry.getKey(); Set<Item> existingItems = entry.getValue(); if (existingItems.equals(items)) { return state; } } return -1; } private Map<Integer, Set<Item>> buildItemSets(Grammar grammar) { // 构建LR(1)项集族 Map<Integer, Set<Item>> itemSets = new HashMap<>(); int state = 0; Set<Item> initialItems = new HashSet<>(); Production startProduction = grammar.getProductions().get(0); initialItems.add(new Item(startProduction, 0, Grammar.EOF)); itemSets.put(state, closure(initialItems, grammar)); boolean changed = true; while (changed) { changed = false; for (Map.Entry<Integer, Set<Item>> entry : new HashMap<>(itemSets).entrySet()) { int currentState = entry.getKey(); Set<Item> currentItems = entry.getValue(); Map<String, Set<Item>> symbolItems = new HashMap<>(); for (Item item : currentItems) { if (item.getDotPosition() < item.getProduction().getRight().size()) { String nextSymbol = item.getNextSymbol(); Set<Item> nextItems = symbolItems.computeIfAbsent(nextSymbol, k -> new HashSet<>()); nextItems.add(new Item(item.getProduction(), item.getDotPosition() + 1, item.getLookahead())); } } for (Map.Entry<String, Set<Item>> symbolEntry : symbolItems.entrySet()) { Set<Item> nextItems = closure(symbolEntry.getValue(), grammar); int nextState = findItemSetState(itemSets, nextItems); if (nextState == -1) { nextState = ++state; itemSets.put(nextState, nextItems); changed = true; } actionTable.put(currentState, new HashMap<>()); actionTable.get(currentState).put(symbolEntry.getKey(), new Action(Action.SHIFT, nextState, null)); } } } return itemSets; } private Set<Item> closure(Set<Item> items, Grammar grammar) { // 计算LR(1)项集的闭包 Set<Item> closure = new HashSet<>(items); boolean changed = true; while (changed) { changed = false; for (Item item : new HashSet<>(closure)) { if (item.getDotPosition() < item.getProduction().getRight().size()) { String nextSymbol = item.getNextSymbol(); Set<Integer> lookaheads = calculateLookahead(item, closure, grammar); for (Production production : grammar.getProductions()) { if (production.getLeft().equals(nextSymbol)) { Item newItem = new Item(production, 0, lookaheads); if (!closure.contains(newItem)) { closure.add(newItem); changed = true; } } } } } } return closure; } private Set<Integer> calculateLookahead(Item item, Set<Item> closure, Grammar grammar) { // 计算LR(1)项的向前看符号集合 Set<Integer> lookaheads = new HashSet<>(); if (item.getDotPosition() == item.getProduction().getRight().size()) { lookaheads.addAll(item.getLookahead()); } else { String nextSymbol = item.getNextSymbol(); Set<Item> lookItems = new HashSet<>(); for (Item closureItem : closure) { if (closureItem.getProduction().getLeft().equals(nextSymbol)) { lookItems.add(closureItem); } } for (Item lookItem : lookItems) { Set<Integer> itemLookaheads = lookItem.getLookahead(); if (itemLookaheads.contains(Grammar.EMPTY)) { lookaheads.addAll(calculateFollowSets(grammar).get(item.getProduction().getLeft())); lookaheads.remove(Grammar.EMPTY); } lookaheads.addAll(itemLookaheads); } } return lookaheads; } private static class Item { private Production production; private int dotPosition; private Set<Integer> lookahead; public Item(Production production, int dotPosition, int lookahead) { this.production = production; this.dotPosition = dotPosition; this.lookahead = new HashSet<>(); this.lookahead.add(lookahead); } public Item(Production production, int dotPosition, Set<Integer> lookahead) { this.production = production; this.dotPosition = dotPosition; this.lookahead = lookahead; } public Production getProduction() { return production; } public int getDotPosition() { return dotPosition; } public String getNextSymbol() { return production.getRight().get(dotPosition); } public Set<Integer> getLookahead() { return lookahead; } @Override public boolean equals(Object obj) { if (obj instanceof Item) { Item other = (Item) obj; return production.equals(other.production) && dotPosition == other.dotPosition && lookahead.equals(other.lookahead); } return false; } @Override public int hashCode() { return Objects.hash(production, dotPosition, lookahead); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(production.getLeft()); builder.append(" ->"); for (int i = 0; i < production.getRight().size(); i++) { if (i == dotPosition) { builder.append(" ·"); } builder.append(" "); builder.append(production.getRight().get(i)); } if (dotPosition == production.getRight().size()) { builder.append(" ·"); } builder.append(", {"); for (int lookahead : lookahead) { builder.append(" '"); builder.append(Grammar.getSymbolString(lookahead)); builder.append("'"); } builder.append(" }"); return builder.toString(); } } private static class Action { public static final int SHIFT = 1; public static final int REDUCE = 2; public static final int ACCEPT = 3; public static final int ERROR = 4; private int type; private int value; private Production production; public Action(int type, int value, Production production) { this.type = type; this.value = value; this.production = production; } public int getType() { return type; } public int getValue() { return value; } public Production getProduction() { return production; } } } ``` 上述代码中,`Grammar`类表示给定的文法,`Token`类表示输入符号串中的一个Token,`LR1Parser`类表示LR(1)分析器,包含了构建LR(1)项集族、构建LR(1)分析表、计算Follow集合、计算First集合、计算闭包、计算向前看符号等功能函数。其中,`buildItemSets()`函数实现了LR(1)项集族的构建,`buildActionTable()`函数实现了LR(1)分析表中的Action部分的构建,`buildGotoTable()`函数实现了LR(1)分析表中的Goto部分的构建,`scan()`函数用于将输入符号串转换为Token序列,`parse()`函数实现了LR(1)分析器的主要逻辑。

相关推荐

最新推荐

recommend-type

4 实验四:LR分析程序的设计与实现

1、了解LR(0)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。 2、掌握LR(0)语法分析方法。
recommend-type

LL(1)分析法实验报告及代码

1.根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。 2.本次实验的目的主要是加深对预测分析LL(1)分析法的理解。
recommend-type

LR(0)语法分析的实现

LR(0)语法分析的实现:对于所输入的LR(0)文法,不论对错,都应有明确的信息告诉外界。对于符合规则的LR(0)文法,将输出LR(0)分析表,并可以对输入的句子进行语法分析输出相应语法树。
recommend-type

LR(0)语法分析的设计与实现.doc

内含代码片段。原理包含CLOSURE和GOTO函数的构造说明,前缀、项目、拓广文法的定义说明,文法项目集规范族的构造伪代码,判断文法是否为LR(0)文法的说明,以及分析表构造讲解与输入串合法性分析步骤。
recommend-type

RTL8188FU-Linux-v5.7.4.2-36687.20200602.tar(20765).gz

REALTEK 8188FTV 8188eus 8188etv linux驱动程序稳定版本, 支持AP,STA 以及AP+STA 共存模式。 稳定支持linux4.0以上内核。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

:YOLO目标检测算法的挑战与机遇:数据质量、计算资源与算法优化,探索未来发展方向

![:YOLO目标检测算法的挑战与机遇:数据质量、计算资源与算法优化,探索未来发展方向](https://img-blog.csdnimg.cn/7e3d12895feb4651b9748135c91e0f1a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5rKJ6YaJ77yM5LqO6aOO5Lit,size_20,color_FFFFFF,t_70,g_se,x_16) # 1. YOLO目标检测算法简介 YOLO(You Only Look Once)是一种
recommend-type

def ObjFun(x,y,beta): # 目标函数 """ Logistic regression loss function :param beta: model parameter vector :param x: feature matrix :param y: label vector :return: loss value """ n = x.shape[0] p = x.shape[1] pred = 1 / (1 + np.exp(-np.dot(x, beta))) pred = np.clip(pred, 1e-15, 1 - 1e-15) # 将预测值限制在一个很小的区间内 ObjVal = -np.sum(y * np.log(pred) + (1 - y) * np.log(1 - pred)) / n return ObjVal

好的,根据上面的目标函数,我们可以推导出其对应的梯度向量函数,如下所示: def gradient(x, y, beta): """ Compute gradient of the logistic regression loss function :param beta: model parameter vector :param x: feature matrix :param y: label vector :return: gradient vector """ n = x.shape[0] pred = 1 /
recommend-type

c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf

校园超市商品信息管理系统课程设计旨在帮助学生深入理解程序设计的基础知识,同时锻炼他们的实际操作能力。通过设计和实现一个校园超市商品信息管理系统,学生掌握了如何利用计算机科学与技术知识解决实际问题的能力。在课程设计过程中,学生需要对超市商品和销售员的关系进行有效管理,使系统功能更全面、实用,从而提高用户体验和便利性。 学生在课程设计过程中展现了积极的学习态度和纪律,没有缺勤情况,演示过程流畅且作品具有很强的使用价值。设计报告完整详细,展现了对问题的深入思考和解决能力。在答辩环节中,学生能够自信地回答问题,展示出扎实的专业知识和逻辑思维能力。教师对学生的表现予以肯定,认为学生在课程设计中表现出色,值得称赞。 整个课程设计过程包括平时成绩、报告成绩和演示与答辩成绩三个部分,其中平时表现占比20%,报告成绩占比40%,演示与答辩成绩占比40%。通过这三个部分的综合评定,最终为学生总成绩提供参考。总评分以百分制计算,全面评估学生在课程设计中的各项表现,最终为学生提供综合评价和反馈意见。 通过校园超市商品信息管理系统课程设计,学生不仅提升了对程序设计基础知识的理解与应用能力,同时也增强了团队协作和沟通能力。这一过程旨在培养学生综合运用技术解决问题的能力,为其未来的专业发展打下坚实基础。学生在进行校园超市商品信息管理系统课程设计过程中,不仅获得了理论知识的提升,同时也锻炼了实践能力和创新思维,为其未来的职业发展奠定了坚实基础。 校园超市商品信息管理系统课程设计的目的在于促进学生对程序设计基础知识的深入理解与掌握,同时培养学生解决实际问题的能力。通过对系统功能和用户需求的全面考量,学生设计了一个实用、高效的校园超市商品信息管理系统,为用户提供了更便捷、更高效的管理和使用体验。 综上所述,校园超市商品信息管理系统课程设计是一项旨在提升学生综合能力和实践技能的重要教学活动。通过此次设计,学生不仅深化了对程序设计基础知识的理解,还培养了解决实际问题的能力和团队合作精神。这一过程将为学生未来的专业发展提供坚实基础,使其在实际工作中能够胜任更多挑战。
recommend-type

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依