LALR语法分析表

LALR语法分析表

  1.LALR(向前看-LR)技术

  2.在实践中常用,分析表比规范LR分析表小

 LALR(1)项集族的内核的高效计算方法

  1.构造G的LR(0)项集族的内核

  2.确定自发生的符号

  3.不断扫描所有项集的内核项,添加传播的符号

 

向前看符号的类型

    public static class Determining {
        public int setId;
        public Production production;
        public int pos;
        public Terminal lookahead;
        /** 1自发生符号2传播符号 */
        public int type;
    }

 

确定向前看符号

private List<Determining> determiningLookahead(Grammar grammar, Map<Integer, SetOfItems> setOfItemsResult,
                                          SetOfItems setOfItems, Item item, Terminal lookaheadStart) {

        LR1 lr1 = new LR1();

        List<Determining> determinings = new ArrayList<>();
        LR1Item lr1Item = LR1Item.of(item.getProduction(), item.getPos(), lookaheadStart);
        SetOfItems newSet = new SetOfItems();
        newSet.add(lr1Item);
        SetOfItems closure = lr1.closure(newSet, grammar);

        Set<LR1Item> closureItems = closure.getItems();
        for (LR1Item closureItem : closureItems) {
            Symbol symbolAfterDot = closureItem.getSymbolAfterDot();
            if (symbolAfterDot == null) {
                continue;
            }
            Integer gotoId = setOfItems.getGotoMap().get(symbolAfterDot);
            if (gotoId == null) {
                continue;
            }
            SetOfItems gotoLalrSet = setOfItemsResult.get(gotoId);
            LR1Item old = (LR1Item) gotoLalrSet.getItem(closureItem.getProduction(), closureItem.getPos() + 1);

            for (Terminal lookahead : closureItem.getLookaheads()) {
                Terminal find = CollectionUtil.find(old.getLookaheads(), lookahead);
                if (find != null) {
                    continue;
                }

                Determining determining = new Determining();
                determining.lookahead = lookahead;
                determining.pos = old.getPos();
                determining.production = old.getProduction();
                determining.setId = gotoLalrSet.getId();

                if (lookahead.equals(lookaheadStart)) {
                    determining.type = 2;// 传播符号
                } else {
                    determining.type = 1;// 自发生符号
                }

                determinings.add(determining);
            }
        }

        return determinings;
    }

 

LALR(1)项集族的内核高效计算方法

public List<SetOfItems> items(Grammar grammar) {

        LR0 lr0 = new LR0();
        LR1 lr1 = new LR1();

        // 1) 构造LR0项集族的内核
        List<SetOfItems> lr0SetOfItem = lr0.items(grammar);
        Map<Integer, SetOfItems> lr0SetMap = new HashMap<>();

        // 删除非内核项
        for (SetOfItems setOfItems : lr0SetOfItem) {
            setOfItems.deleteNonKernelItems(grammar);
            SetOfItems pre = lr0SetMap.put(setOfItems.getId(), setOfItems);
            if (pre != null) {
                throw new RuntimeException("已经存在项集ID:" + setOfItems.getId());
            }
        }

        // 用LR0项集初始化结果LALR项集
        List<SetOfItems> result = new ArrayList<>();
        Map<Integer, SetOfItems> setOfItemsResult = new HashMap<>();

        for (SetOfItems setOfItems : lr0SetOfItem) {
            System.err.println("LR0 项集:" + setOfItems.getId());
            for (Item item : setOfItems.getItems()) {
                System.err.println(item.toString());
            }

            SetOfItems lalrSet = new SetOfItems();
            lalrSet.setId(setOfItems.getId());
            lalrSet.getGotoMap().putAll(setOfItems.getGotoMap());
            Set<Item> items = setOfItems.getItems();
            for (Item item : items) {
                if (item.getProduction().getHead().equals(grammar.start) && item.getPos() == 0) {
                    // 初始项的自发生成的向前看符号$
                    lalrSet.add(LR1Item.of(item.getProduction(), item.getPos(), Terminal.dollar));
                } else {
                    lalrSet.add(LR1Item.of(item.getProduction(), item.getPos(), (Terminal) null));
                }
            }
            result.add(lalrSet);
            setOfItemsResult.put(lalrSet.getId(), lalrSet);
        }

        // 2)确定自发生成的符号
        for (SetOfItems lr0set : lr0SetOfItem) {// 项集族的每个项集
            Set<Item> items = lr0set.getItems();
            for (Item item : items) {// 项集中每个项

                List<Determining> determiningList = determiningLookahead(grammar, setOfItemsResult, lr0set, item, Terminal.sharp);
                for (Determining determining : determiningList) {
                    if (determining.type != 1) {
                        continue;
                    }
                    SetOfItems lalrSet = setOfItemsResult.get(determining.setId);
                    LR1Item gotoItem = (LR1Item) lalrSet.getItem(determining.production, determining.pos);
                    gotoItem.addLookahead(determining.lookahead);
                }
            }
        }

        for (SetOfItems setOfItems : result) {
            System.err.println("初始 项集:" + setOfItems.getId());
            for (Item item : setOfItems.getItems()) {
                System.err.println(item);
            }
        }

        // 3)不断扫描所有项集的内核项
        boolean hasNew;
        int count = 0;
        do {
            hasNew = false;
            count++;

            System.err.println("第" + count + "趟扫描");
            List<Determining> determinings = new ArrayList<>();

            List<SetOfItems> tmpSets = new ArrayList<>(result);
            for (SetOfItems lalrSet : tmpSets) {
                Set<LR1Item> lalrItemSet = lalrSet.getItems();
                for (LR1Item lalrItem : lalrItemSet) {

                    if (lalrItem.getLookaheads() == null) {
                        continue;
                    }

                    for (Terminal lookaheadStart : lalrItem.getLookaheads()) {

                        List<Determining> determiningList = determiningLookahead(grammar, setOfItemsResult, lalrSet, lalrItem, lookaheadStart);
                        for (Determining determining : determiningList) {
                            if (determining.type == 1) {
                                continue;
                            }
                            determinings.add(determining);
                            hasNew = true;
                        }
                    }
                }

            }

            for (Determining determining : determinings) {
                SetOfItems setOfItems = setOfItemsResult.get(determining.setId);
                LR1Item old = (LR1Item) setOfItems.getItem(determining.production, determining.pos);
                old.addLookahead(determining.lookahead);
                System.err.println("状态" + determining.setId + "项" + old + "添加传播符号" + determining.lookahead);
            }

            for (SetOfItems setOfItems : result) {
                System.err.println("项集:" + setOfItems.getId());
                for (Item item : setOfItems.getItems()) {
                    System.err.println(item);
                }
            }

        } while (hasNew);

        // 将LALR(1)内核通过CLOSURE求闭包转换为LR(1)项集
        List<SetOfItems> lr1Set = new ArrayList<>();
        for (SetOfItems lalrSet : result) {
            SetOfItems closure = lr1.closure(lalrSet, grammar);
            closure.setId(lalrSet.getId());
            closure.getGotoMap().putAll(lalrSet.getGotoMap());
            lr1Set.add(closure);
        }

        return lr1Set;
    }

 

posted @ 2023-11-15 23:55  kashin05  阅读(214)  评论(0)    收藏  举报