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  }