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 }