首页 > 其他分享 >构造SLR语法分析表

构造SLR语法分析表

时间:2023-11-04 11:44:07浏览次数:29  
标签:set grammar symbol 构造 SLR new 语法分析 setId result

构造SLR语法分析表

方法:

1)构造G‘的规范LR(0)项集族

2)根据规则生成动作

3)生成转换

4)设置报错

/**
     * P157 规范LR(0)项集族
     * @param grammar
     */
    public List<SetOfItems> items(Grammar grammar) {

        int setId = 0;

        List<SetOfItems> result = new ArrayList<>();
        Map<Symbol, SetOfItems> gotoMap = new HashMap<>();

        List<Production> production = grammar.getProduction(grammar.start);

        // 开始状态
        SetOfItems startSet = new SetOfItems();
        startSet.add(Item.of(production.get(0), 0));
        startSet = closure(startSet, grammar);
        startSet.setId(setId++);
        result.add(startSet);

        boolean hasNew;// 是否产生新的项集
        do {
            hasNew = false;
            List<SetOfItems> allSet = new ArrayList<>(result);
            for (SetOfItems setOfItems : allSet) {
                for (Symbol symbol : grammar.allSymbols) {

                    SetOfItems gotoTarget = gotoSet(grammar, setOfItems, symbol);
                    // 在符号symbol上没有GOTO集合
                    if (gotoTarget == null) {
                        continue;
                    }

                    // 判断项集是否已经存在
                    SetOfItems pre = CollectionUtil.find(result, gotoTarget);
                    if (pre != null) {// 已经存在只记录GOTO
                        setOfItems.addGoto(symbol, pre);
                        continue;
                    }

                    gotoTarget.setId(setId++);
                    setOfItems.addGoto(symbol, gotoTarget);
                    result.add(gotoTarget);
                    hasNew = true;
                }
            }
        } while (hasNew);


        return result;
    }

 语法分析表的结构

1.动作函数ACTION,移入,规约,接受,报错

2.转换函数GOTO

/**
 * 语法分析表
 */
public class ParsingTable {

    private Map<Integer, Map<Symbol, Action>> set_symbol_action = new HashMap<>();
    private Map<Integer, Map<Symbol, Integer>> set_symbol_set = new HashMap<>();

    public void addAction(int fromId, Symbol symbol, Action action) {
        Map<Symbol, Action> actionMap = set_symbol_action.computeIfAbsent(fromId, k -> new HashMap<>());
        actionMap.put(symbol, action);
    }

    public void addGoto(int fromId, Symbol symbol, int toId) {
        Map<Symbol, Integer> actionMap = set_symbol_set.computeIfAbsent(fromId, k -> new HashMap<>());
        actionMap.put(symbol, toId);
    }

    public Action getAction(int setId, Symbol symbol) {
        Map<Symbol, Action> actionMap = set_symbol_action.get(setId);
        if (actionMap == null) {
            return null;
        }
        return actionMap.get(symbol);
    }


    public Integer gotoSet(int setId, Symbol symbol) {
        Map<Symbol, Integer> setMap = set_symbol_set.get(setId);
        if (setMap == null) {
            return null;
        }
        return setMap.get(symbol);
    }
}

构建语法分析表

/**
     * P161 算法4.46 构造一个SLR语法分析表
     * @param grammar
     * @param setList
     * @return
     */
    public ParsingTable buildParsingTable(Grammar grammar, List<SetOfItems> setList) {
        ParsingTable result = new ParsingTable();

        for (SetOfItems from : setList) {

            for (Item item : from.getItems()) {

                if (item.pos != item.getProduction().getBody().size()) {
                    continue;
                }

                Nonterminal head = item.getProduction().getHead();
                if (head.equals(grammar.start)) {
                    // 如果[S' -> S·]在I中,那么将ACTION[i $]设置为接受
                    Set<Terminal> follows = grammar.follow(head);
                    for (Terminal symbol : follows) {
                        result.addAction(from.getId(), symbol, AcceptAction.of());
                    }
                } else {
                    // 如果[A -> α·]在I中,那么对于所有FOLLOW(A)中的所有a,将ACTION[i a]设置为规约
                    Set<Terminal> follows = grammar.follow(head);
                    for (Terminal symbol : follows) {
                        result.addAction(from.getId(), symbol, ReduceAction.of(item.getProduction()));
                    }
                }
            }

            for (Map.Entry<Symbol, SetOfItems> entry : from.getGotoMap().entrySet()) {
                Symbol symbol = entry.getKey();
                SetOfItems to = entry.getValue();

                // 如果[A -> α·aβ]在from中并且GOTO(from, a) = to,那么将Action[from,a]设置为移入to,a必须为一个终结符
                if (symbol instanceof Terminal) {
                    result.addAction(from.getId(), symbol, ShiftAction.of(to.getId()));
                } else {
                    result.addGoto(from.getId(), symbol, to.getId());
                }

            }
        }

        return result;
    }

 

标签:set,grammar,symbol,构造,SLR,new,语法分析,setId,result
From: https://www.cnblogs.com/kashin/p/17795622.html

相关文章

  • JavaScript 函数、函数构造、函数调用、参数、函数返回值、变量的作用域、预解析
    一、函数及函数的构造函数是一个可重用的代码块,用来完成某个特定功能。每当需要反复执行一段代码时,可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行,就可以避免页面载入时执行该脚本简单来说就是一个封装,封装的是一个特定的功能,重复使用函......
  • C++构造函数初始化列表
    构造函数的一项重要功能是对成员变量进行初始化,为了达到这个目的,可以在构造函数的函数体中对成员变量一一赋值,还可以采用初始化列表。C++构造函数的初始化列表使得代码更加简洁,请看下面的例子:#include<iostream>usingnamespacestd;classStudent{private:......
  • C++ 移动构造函数详解
    目录移动构造函数是什么?复制构造和移动构造对比改进的拷贝构造移动构造实现移动构造优点左值、右值、左值引用、右值引用std::move参考移动构造函数是什么?移动构造是C++11标准中提供的一种新的构造方法。先举个生活例子,你有一本书,你已经不想看了,但我非常想看,那么我有哪......
  • 【深度学习】PyTorch的基本运算 与 构造简单神经网络模型
    基本运算importtorch#创建一个自定义的张量t=torch.tensor([1.0,2.0,3.0])#tensor([1.,2.,3.])#求平均值t.mean()#tensor(2.)#创建一个指定行列的张量x=torch.empty(3,5)#tensor([[0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.],[0.,0.,0.,0.,0.]......
  • 20231101构造题记录
    20231101构造题记录A.人生的经验可以对于每个长度为\(l-1\)的串建一个点,每个点有\(c\)个后继状态,也有\(c\)个入边,所以一定可以找到一个欧拉路因此答案为\(c^l+l-1\)即所有可能的串首尾相接拼起来的长度考虑用一个圈套圈求欧拉路,即每次拓展一个点,用栈维护,如果不能继......
  • 当我们在谈论构造函数注入的时候我们在谈论什么
    依赖注入当涉及依赖注入(DependencyInjection,DI)时,首先推荐使用构造函数注入,因为构造函数注入有很多技术优点,而且还与面向对象的设计原则密切相关。在业界,构造函数注入作为依赖注入的一种最佳实践得到了广泛的认可,在SpringFramework的作者之一RodJohnson的观点中也得有体现。下......
  • 算数题构造存入CSV
    ShiYong.javapackagerjgz;importjava.io.FileWriter;importjava.io.IOException;importjava.util.Scanner;publicclassShiYong{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);System.out.print(&qu......
  • Python构造代理IP池提高访问量
    前言爬虫程序是批量获取互联网上的信息的重要工具,在访问目标网站时需要频繁发送请求,为了避免被目标网站封禁IP地址,我们需要使用代理IP来代替自己的IP地址进行访问。本文将介绍如何使用Python构建代理IP池,让爬虫程序更加稳定和高效地运行。一、代理IP是什么代理IP是指由第......
  • mysql将某一个月所有天数构造出来
    写项目时会遇到统计某个月每一天数据的场景mysql可以将某个月的所有日期构造出来DAY()函数:返回给定日期的月份的日期部分LAST_DAY()函数:返回某个月最后一天的日期STR_TO_DATE()函数:将字符串格式转换成日期格式ADDDATE()函数:将指定的日期值添加到现有日期上,并返回结果SELE......
  • 使用Lombok@Builder、@Data(没有生成无参构造方法)这个坑要注意,使用@Builder时配合@NoAr
    使用Lombok@Builder、@Data(没有生成无参构造方法)这个坑要注意,,使用@Builder时配合@NoArgsConstructor和@AllArgsConstructor一起使用Lombok为我们开发带来了极大便利,特别是在想要使用建造者模式的时候只需要在类上加@Builder注解即可。但是不小心也会引发隐藏的bug。我们来看......