github.com/jmigpin/editor@v1.6.0/util/parseutil/lrparser/verticesdata.go (about) 1 package lrparser 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // passes rules (ruleindex) to vertices data 9 type VerticesData struct { 10 verts []*Vertex 11 rFirst *RuleFirstT 12 reverse bool 13 } 14 15 func newVerticesData(ri *RuleIndex, startRuleName string, reverse bool) (*VerticesData, error) { 16 vd := &VerticesData{reverse: reverse} 17 18 if err := ri.derefRules(); err != nil { 19 return nil, err 20 } 21 22 vAutoId := 0 23 addNewVertexAutoId := func() *Vertex { 24 v := newVertex(VertexId(vAutoId)) 25 vAutoId++ 26 vd.verts = append(vd.verts, v) 27 return v 28 } 29 30 dr0, err := ri.startRule(startRuleName) 31 if err != nil { 32 return nil, err 33 } 34 35 vd.rFirst = newRuleFirstT(ri, vd.reverse) 36 37 rd0 := newRuleDot(startRule, dr0, vd.reverse) 38 rdlas0 := RuleDotsLaSet{} 39 rdlas0.setRule(*rd0, endRule) 40 41 v0 := addNewVertexAutoId() 42 v0.rdslasK = rdlas0 43 v0.rdslasC = rdlasClosure(rdlas0, vd.rFirst) 44 45 stk := []*Vertex{} 46 stk = append(stk, v0) 47 seenV := map[string]*Vertex{} 48 for len(stk) > 0 { 49 k := len(stk) - 1 50 v1 := stk[k] // top 51 stk = stk[:k] // pop 52 53 //println("***") 54 //fmt.Printf("rdslasC %v\n", v1.rdslasC.ruleDots()) 55 rset := v1.rdslasC.ruleDots().dotRulesSet() 56 //fmt.Printf("rset %v\n", rset) 57 for _, x := range rset.sorted() { // stable, otherwise alters vertex creation order and will fail tests 58 //fmt.Printf("***%v\n", x) 59 60 rdslasK, rdslasC := rdlasGoto(v1.rdslasC, x, vd.rFirst) 61 if len(rdslasK) == 0 { 62 continue 63 } 64 65 j := rdslasK.String() // union of sets with the same core 66 v2, ok := seenV[j] 67 if !ok { 68 v2 = addNewVertexAutoId() 69 v2.rdslasK = rdslasK 70 v2.rdslasC = rdslasC 71 seenV[j] = v2 72 stk = append(stk, v2) 73 } 74 v1.gotoVert[x] = v2 75 76 } 77 } 78 79 return vd, nil 80 } 81 82 //---------- 83 84 func (vd *VerticesData) String() string { 85 sb := &strings.Builder{} 86 for _, v := range vd.verts { 87 fmt.Fprintf(sb, "%v\n", v) 88 } 89 return strings.TrimSpace(sb.String()) 90 } 91 92 //---------- 93 //---------- 94 //---------- 95 96 func rdlasGoto(rdlas RuleDotsLaSet, x Rule, rFirst *RuleFirstT) (RuleDotsLaSet, RuleDotsLaSet) { 97 res := RuleDotsLaSet{} 98 for rd, laSet := range rdlas { 99 if r, ok := rd.dotRule(); ok && r == x { 100 rd2, _ := rd.advanceDot() 101 res.setRuleSet(*rd2, laSet) 102 } 103 } 104 return res, rdlasClosure(res, rFirst) 105 } 106 107 //---------- 108 //---------- 109 //---------- 110 111 func rdlasClosure(rdslas RuleDotsLaSet, rFirst *RuleFirstT) RuleDotsLaSet { 112 res := RuleDotsLaSet{} 113 114 type entry struct { 115 rd *RuleDot 116 las RuleSet 117 } 118 119 stk := []*entry{} 120 121 // provided rdslas (kernels) are part of the closure 122 for rd, las := range rdslas { 123 rd2 := rd 124 stk = append(stk, &entry{&rd2, las}) 125 res.setRuleSet(rd, las) 126 } 127 128 for len(stk) > 0 { 129 k := len(stk) - 1 130 e := stk[k] // top 131 stk = stk[:k] // pop 132 133 // [A->α.Bβ,a], B->γ, b in first(βa), add [B->.γ,b] 134 // A = rdla.rd.prod 135 136 B, ok := e.rd.dotRule() 137 if !ok { 138 continue 139 } 140 141 if B.isTerminal() { 142 continue 143 } 144 BProds := ruleProductions(B) 145 146 β := []Rule{} 147 rd2, ok := e.rd.advanceDot() 148 if ok { 149 w := rd2.dotAndAfterRules() 150 β = append(β, w...) 151 } 152 153 for a := range e.las { 154 βa := append(β, a) 155 firstβa := rFirst.sequenceFirst(βa) 156 for _, γ := range BProds { 157 rd3 := newRuleDot(B, γ, rFirst.reverse) 158 159 las := RuleSet{} 160 for b := range firstβa { // b is terminal 161 if !res.hasRule(*rd3, b) { 162 res.setRule(*rd3, b) 163 las.set(b) 164 } 165 } 166 // add to continue processing 167 if len(las) > 0 { 168 stk = append(stk, &entry{rd3, las}) 169 } 170 } 171 } 172 } 173 174 return res 175 } 176 177 //---------- 178 //---------- 179 //---------- 180 181 type Vertex struct { 182 id VertexId 183 rdslasK RuleDotsLaSet // kernels 184 rdslasC RuleDotsLaSet // closure 185 gotoVert map[Rule]*Vertex // goto vertex 186 } 187 188 func newVertex(id VertexId) *Vertex { 189 v := &Vertex{id: id} 190 v.gotoVert = map[Rule]*Vertex{} 191 return v 192 } 193 func (v *Vertex) String() string { 194 s := fmt.Sprintf("%v:\n", v.id) 195 196 // print kernels/rdlas 197 s += indentStr("\t", v.rdslasC.String()) 198 199 // print edges 1 (rule->vertex) 200 w := []Rule{} 201 for e := range v.gotoVert { 202 w = append(w, e) 203 } 204 sortRules(w) 205 u := []string{} 206 for _, r := range w { 207 v2 := v.gotoVert[r] 208 u = append(u, fmt.Sprintf("%v->%v", r.id(), v2.id)) 209 } 210 s += indentStr("\t", strings.Join(u, "\n")) 211 212 //// print edges 2 (vertex<-rule) 213 //m2 := map[*Vertex][]Rule{} 214 //w := []*Vertex{} 215 //for r, v := range v.edges { 216 // w = append(w, v) 217 // m2[v] = append(m2[v], r) 218 //} 219 //sort.Slice(w, func(a, b int) bool { 220 // return w[a].id < w[b].id 221 //}) 222 //for _, v := range w { 223 // u := []string{} 224 // for _, r := range m2[v] { 225 // u = append(u, fmt.Sprintf("%v", r.id())) 226 // } 227 // s += fmt.Sprintf("\t%v<-%v\n", v.id, strings.Join(u, ";")) 228 //} 229 230 return strings.TrimSpace(s) 231 } 232 233 //---------- 234 //---------- 235 //---------- 236 237 type VertexId int 238 239 func (vid VertexId) String() string { 240 return fmt.Sprintf("vertex%v", int(vid)) 241 }