zoukankan      html  css  js  c++  java
  • 【编译原理】提取左部公因子算法

    下面是书中给出的算法, 简单的描述了两句。但是实际上实现起来没有那么简单。

    在百度搜索提取左部公因算法时也只有理论上的知识,并没有实际的算法。

     https://github.com/hixiaosan/dragon_algorithm.git

    type Tree struct {
        Root *Node
    }
    
    type Node struct {
        Child []*Node  // 子节点
        Pros []*Production       // 产生式索引
        Sym  Symbolic // 当前符号
    }
    
    // 生成分析树
    func InitProductionTree(parent *Node, pros []*Production, idx int) {
    
        fmt.Println("InitProductionTree")
        groupPros := make(map[Symbolic][]*Production)
    
        for i := 0; i < len(pros); i++ {
            if len(pros[i].body) > idx {
                sym := *pros[i].body[idx]
                if _, ok := groupPros[sym]; !ok {
                    groupPros[sym] = make([]*Production, 0);
                }
    
                groupPros[sym] = append(groupPros[sym], pros[i])
            }
        }
    
        for k, v := range groupPros {
            fmt.Println(k)
            if len(v) > 1 { // 重复前缀大于 1个的 加入子节点
        
                child := &Node{Child: make([]*Node, 0), Pros:v, Sym: k}
                parent.Child = append(parent.Child, child)
    
                InitProductionTree(child, groupPros[k], idx + 1)
            }
        }
        fmt.Println(len(parent.Child))
    
    
    }
    
    
    
    // 提取左部公因子
    func TakeCommonLeft(pros [] *Production) ([]*Production) {
        result := make([]*Production, 0)
        multPro := GroupProduction(pros)
        
        
        for i := 0; i < len(multPro);  {
            pro := multPro[i]
            var tree Tree
            tree.Root = &Node{Child: make([]*Node, 0)}
    
            fmt.Println("LOOP: ---------------------", i)
            InitProductionTree(tree.Root, pro.pros, 0)
            if len(tree.Root.Child) == 0 { // 没有公共前缀
                i++
                
                continue
            }
    
            // 有公共前缀的处理
            root := tree.Root
            last := root
            var deep int  = 0 // 层次
            preSymbolic := make([]Symbolic, 0)
            for  {
                if len(root.Child) == 1 { // 前缀全部相同, 进入下一层
                    last = root
                    root = root.Child[0]
                    preSymbolic = append(preSymbolic, root.Sym) // 前缀符号
                    deep++
                    continue
                }
    
                if len(root.Child) > 1 || (len(root.Child) == 0 && deep != 0) {
                    
                    // 前缀不是全部相同
    
                    nmPros := &MultProduction{header: pro.header + "`", pros: make([]*Production, 0)} // 新的产生式集合
                    fmt.Println("----------------------,", len(root.Child), deep)
                    
                    if deep != 0 { // 不是第一层
                        newProc := &Production{header: pro.header}
    
                        for _, sym := range preSymbolic {
                            newProc.body = append(newProc.body, &Symbolic{sym_type: sym.sym_type, sym: sym.sym})
                        }
    
                        newProc.body = append(newProc.body, &Symbolic{sym_type: SYM_TYPE_N_TERMINAL, sym: newProc.header + "`"})
    
                        newPros := make([]*Production, 0)
    
                        root = last // 回到上一层
                        newPros = append(newPros, newProc)
    
                        for _, pro := range multPro[i].pros {
                            NTProc := &Production{header: pro.header + "`", body: make([]*Symbolic, 0)}
                            fmt.Println(pro.header, pro.body[0])
                            NTProc.body = append(NTProc.body, pro.body[deep:]...)
                            nmPros.pros = append(nmPros.pros, NTProc)
                        }
    
                        multPro[i].pros = newPros
                    } else { // 第一层
    
                        for _, c := range root.Child {
                            preSymbolic = preSymbolic[0:0]
                            preSymbolic = append(preSymbolic, c.Sym) // 前缀符号
    
                            newProc := &Production{header: pro.header}
    
                            for _, sym := range preSymbolic {
                                newProc.body = append(newProc.body, &Symbolic{sym_type: sym.sym_type, sym: sym.sym})
                            }
    
                            newProc.body = append(newProc.body, &Symbolic{sym_type: SYM_TYPE_N_TERMINAL, sym: newProc.header + "`"})
    
                            newPros := make([]*Production, 0)
    
                            for _, org_pro := range multPro[i].pros {
                                find := false
                                for _, del := range c.Pros {
            
                                    if del == org_pro {
                                        find = true
                                        NTProc := &Production{header: pro.header + "`", body: make([]*Symbolic, 0)}
                                        NTProc.body = append(NTProc.body, del.body[1:]...)
    
                                        // 防止符号重复
                                        exists := false
                                        f:for _, pro := range nmPros.pros {
                                            if len(pro.body) != len(NTProc.body) {
                                                continue
                                            }
    
                                            for _t := 0; _t < len(pro.body); _t++ {
                                                if *pro.body[_t] != *NTProc.body[_t] {
                                                    break 
                                                }
    
                                                if _t + 1 == len(pro.body) {
                                                    exists = true
                                                    break f
                                                }
                                            }
                                        }
    
                                        if false == exists {
                                            nmPros.pros = append(nmPros.pros, NTProc)
                                        }
                                        break
                                    }
                                }
    
                                if find == false {
                                    newPros = append(newPros, org_pro)
                                }
                            }
    
                            newPros = append(newPros, newProc)
                            multPro[i].pros = newPros
                        }
                        
                    }
    
                    multPro = append(multPro, nmPros)
                    break
                }
                
    
            }
        }
    
    
        for i := 0; i < len(multPro);  i++ {
            result = append(result, multPro[i].pros...)
        }
    
    
        return result
    }

    https://github.com/hixiaosan/dragon_algorithm.git

  • 相关阅读:
    软考
    十步走-阅读笔记
    软著申请
    十步走-阅读笔记
    基于Ubuntu安装部署ZooKeeper
    基于Ubuntu安装JDK(OPenJDK8)
    Intern Day89
    阿里巴巴Java研发工程师技术一面
    面试
    6_moc.md
  • 原文地址:https://www.cnblogs.com/lxykl/p/10106753.html
Copyright © 2011-2022 走看看