1. 程式人生 > >【編譯原理】提取左部公因子演算法

【編譯原理】提取左部公因子演算法

下面是書中給出的演算法, 簡單的描述了兩句。但是實際上實現起來沒有那麼簡單。

在百度搜索提取左部公因演算法時也只有理論上的知識,並沒有實際的演算法。

 

 

 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