github.com/jmigpin/editor@v1.6.0/util/parseutil/lrparser/ruledot.go (about)

     1  package lrparser
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  )
     8  
     9  type RuleDot struct { // also know as "item"
    10  	prod    Rule // producer: "prod->rule"
    11  	rule    Rule // producee: where the dot runs
    12  	dot     int  // rule dot
    13  	reverse bool
    14  }
    15  
    16  func newRuleDot(prod, rule Rule, reverse bool) *RuleDot {
    17  	rd := &RuleDot{prod: prod, rule: rule}
    18  	if reverse && ruleProdCanReverse(prod) {
    19  		rd.reverse = true
    20  		//rd.dot = len(rd.sequence())
    21  	}
    22  	rd.advanceDotNils()
    23  	return rd
    24  }
    25  
    26  //----------
    27  
    28  func (rd *RuleDot) sequence() []Rule {
    29  	return ruleSequence(rd.rule, rd.reverse)
    30  }
    31  
    32  //----------
    33  
    34  func (rd *RuleDot) dotRule() (Rule, bool) {
    35  	if rd.dotAtEnd() {
    36  		return nil, false
    37  	}
    38  	w := rd.sequence()
    39  	//if rd.reverse {
    40  	//	return w[rd.dot-1], true
    41  	//}
    42  	return w[rd.dot], true
    43  }
    44  func (rd *RuleDot) dotAtEnd() bool {
    45  	//if rd.reverse {
    46  	//	return rd.dot == 0
    47  	//}
    48  	return rd.dot == len(rd.sequence())
    49  }
    50  func (rd *RuleDot) dotAndAfterRules() []Rule {
    51  	// assumes valid dot
    52  	w := rd.sequence()
    53  	//if rd.reverse {
    54  	//	//return reverseRulesCopy(w[:rd.dot])
    55  	//	return w[:rd.dot]
    56  	//}
    57  	return w[rd.dot:]
    58  }
    59  
    60  //----------
    61  
    62  func (rd *RuleDot) advanceDot() (*RuleDot, bool) {
    63  	if rd.dotAtEnd() {
    64  		return nil, false
    65  	}
    66  	rd2 := *rd // copy
    67  	rd2.blindlyAdvanceDot()
    68  	rd2.advanceDotNils()
    69  	return &rd2, true
    70  }
    71  func (rd *RuleDot) blindlyAdvanceDot() {
    72  	//if rd.reverse {
    73  	//	rd.dot--
    74  	//} else {
    75  	//	rd.dot++
    76  	//}
    77  	rd.dot++
    78  }
    79  func (rd *RuleDot) advanceDotNils() {
    80  	for {
    81  		r, ok := rd.dotRule()
    82  		if ok && r == nilRule {
    83  			rd.blindlyAdvanceDot()
    84  			continue
    85  		}
    86  		break
    87  	}
    88  }
    89  
    90  //----------
    91  
    92  func (rd *RuleDot) popLen() int {
    93  	w := rd.sequence()
    94  	// don't count nils
    95  	k := 0
    96  	for _, r := range w {
    97  		if r == nilRule {
    98  			continue
    99  		}
   100  		k++
   101  	}
   102  	return k
   103  }
   104  
   105  //----------
   106  
   107  func (rd *RuleDot) String() string {
   108  	rev := ""
   109  	if rd.reverse {
   110  		rev = "rev:"
   111  	}
   112  	return fmt.Sprintf("{%v%v,%v->%v}", rev, rd.dot, rd.prod.id(), rd.rule.id())
   113  }
   114  
   115  //----------
   116  //----------
   117  //----------
   118  
   119  type RuleDots []*RuleDot
   120  
   121  func (rds RuleDots) has(rd *RuleDot) bool {
   122  	for _, rd2 := range rds {
   123  		if *rd2 == *rd {
   124  			return true
   125  		}
   126  	}
   127  	return false
   128  }
   129  func (rds RuleDots) dotRulesSet() RuleSet {
   130  	rset := RuleSet{}
   131  	for _, rd := range rds {
   132  		if r, ok := rd.dotRule(); ok {
   133  			rset.set(r)
   134  		}
   135  	}
   136  	return rset
   137  }
   138  func (rds RuleDots) sorted() RuleDots {
   139  	w := make(RuleDots, len(rds))
   140  	copy(w, rds)
   141  	sortRuleDots(w)
   142  	return w
   143  }
   144  func (rds RuleDots) String() string {
   145  	s := "ruledots:\n"
   146  	rds = rds.sorted()
   147  	for _, rd := range rds {
   148  		s += fmt.Sprintf("\t%v\n", rd)
   149  	}
   150  	return strings.TrimSpace(s)
   151  }
   152  
   153  //----------
   154  //----------
   155  //----------
   156  
   157  func sortRuleDots(w RuleDots) {
   158  	sort.Slice(w, func(a, b int) bool {
   159  		ra, rb := w[a], w[b]
   160  		va1, va2, va3, va4, va5 := sortRuleDotsValue(ra)
   161  		vb1, vb2, vb3, vb4, vb5 := sortRuleDotsValue(rb)
   162  		if va1 == vb1 {
   163  			if va2 == vb2 {
   164  				if va3 == vb3 {
   165  					if va4 == vb4 {
   166  						return va5 < vb5
   167  					}
   168  					return va4 < vb4
   169  				}
   170  				return va3 < vb3
   171  			}
   172  			return va2 < vb2
   173  		}
   174  		return va1 < vb1
   175  	})
   176  }
   177  func sortRuleDotsValue(rd *RuleDot) (int, string, int, string, int) {
   178  	ta, sa := sortRulesValue(rd.prod)
   179  	tb, sb := sortRulesValue(rd.rule)
   180  	return ta, sa, tb, sb, rd.dot
   181  }