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

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

 

 

 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

posted on 2018-12-12 09:58  lxykl  阅读(1878)  评论(0编辑  收藏  举报