github.com/jmigpin/editor@v1.6.0/util/parseutil/lrparser/node.go (about) 1 package lrparser 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/jmigpin/editor/util/parseutil" 9 ) 10 11 type PState struct { 12 *parseutil.Scanner 13 Node PNode 14 } 15 16 func NewPState(src []byte) *PState { 17 ps := &PState{} 18 ps.Scanner = parseutil.NewScanner() 19 ps.SetSrc(src) 20 return ps 21 } 22 23 //---------- 24 //---------- 25 //---------- 26 27 type RuneRange = parseutil.RuneRange 28 type RuneRanges = parseutil.RuneRanges 29 type PosError = parseutil.ScPosError 30 31 //---------- 32 //---------- 33 //---------- 34 35 // parse node 36 type PNode interface { 37 Pos() int 38 End() int 39 } 40 41 //---------- 42 43 func PNodeBytes(node PNode, src []byte) []byte { 44 pos, end := node.Pos(), node.End() 45 if pos > end { 46 pos, end = end, pos 47 } 48 return src[pos:end] 49 } 50 func PNodeString(node PNode, src []byte) string { 51 return string(PNodeBytes(node, src)) 52 } 53 func PNodePosStr(node PNode) string { 54 return fmt.Sprintf("[%v:%v]", node.Pos(), node.End()) 55 } 56 57 //func pnodeSrc2(node PNode, fset *FileSet) string { 58 // return string(PNodeBytes(node, fset.Src)) 59 //} 60 61 //---------- 62 //---------- 63 //---------- 64 65 // basic parse node implementation 66 type BasicPNode struct { 67 pos int // can have pos>end when in reverse 68 end int 69 } 70 71 func (n *BasicPNode) Pos() int { 72 return n.pos 73 } 74 func (n *BasicPNode) End() int { 75 return n.end 76 } 77 func (n *BasicPNode) SetPos(pos, end int) { 78 n.pos = pos 79 n.end = end 80 } 81 func (n *BasicPNode) PosEmpty() bool { 82 return n.pos == n.end 83 } 84 func (n *BasicPNode) SrcString(src []byte) string { 85 return string(src[n.pos:n.end]) 86 } 87 88 //---------- 89 //---------- 90 //---------- 91 92 // content parser node 93 type CPNode struct { 94 BasicPNode 95 rule Rule // can be nil in state0 96 childs []*CPNode 97 data interface{} 98 simulated bool 99 } 100 101 func newCPNode(pos, end int, r Rule) *CPNode { 102 cpn := &CPNode{rule: r} 103 cpn.SetPos(pos, end) 104 return cpn 105 } 106 func newCPNode2(n1, n2 PNode, r Rule) *CPNode { 107 return newCPNode(n1.Pos(), n2.End(), r) 108 } 109 110 //---------- 111 112 func (cpn *CPNode) addChilds(reverse bool, cs ...*CPNode) { 113 if reverse { 114 // wARNING: changes slice order 115 for i := 0; i < len(cs)/2; i++ { 116 k := len(cs) - 1 - i 117 cs[i], cs[k] = cs[k], cs[i] 118 } 119 120 cpn.childs = append(cs, cpn.childs...) 121 } else { 122 cpn.childs = append(cpn.childs, cs...) 123 } 124 } 125 126 //---------- 127 //---------- 128 //---------- 129 130 type BuildNodeFn func(*BuildNodeData) error 131 132 //---------- 133 134 type BuildNodeData struct { 135 cpr *cpRun 136 cpn *CPNode 137 } 138 139 func newBuildNodeData(cpr *cpRun, cpn *CPNode) *BuildNodeData { 140 return &BuildNodeData{cpr: cpr, cpn: cpn} 141 } 142 func (d *BuildNodeData) Pos() int { 143 return d.cpn.Pos() 144 } 145 func (d *BuildNodeData) End() int { 146 return d.cpn.End() 147 } 148 149 func (d *BuildNodeData) NodeSrc() string { 150 return PNodeString(d.cpn, d.cpr.ps.Src) 151 } 152 func (d *BuildNodeData) FullSrc() []byte { 153 return d.cpr.ps.Src 154 } 155 func (d *BuildNodeData) Data() interface{} { 156 return d.cpn.data 157 } 158 func (d *BuildNodeData) SetData(v interface{}) { 159 d.cpn.data = v 160 } 161 func (d *BuildNodeData) IsEmpty() bool { 162 return d.cpn.PosEmpty() 163 } 164 func (d *BuildNodeData) ExternalData() any { 165 return d.cpr.externalData 166 } 167 168 //---------- 169 170 func (d *BuildNodeData) SprintRuleTree(maxDepth int) string { 171 return SprintNodeTree(d.cpr.ps.Src, d.cpn, maxDepth) 172 } 173 func (d *BuildNodeData) PrintRuleTree(maxDepth int) { 174 fmt.Printf("%v\n", d.SprintRuleTree(maxDepth)) 175 } 176 177 // TODO: func to print cpnode.data if present 178 179 //---------- 180 181 func (d *BuildNodeData) ChildsLen() int { 182 return len(d.cpn.childs) 183 } 184 func (d *BuildNodeData) Child(i int) *BuildNodeData { 185 return newBuildNodeData(d.cpr, d.cpn.childs[i]) 186 } 187 func (d *BuildNodeData) ChildStr(i int) string { 188 return PNodeString(d.cpn.childs[i], d.cpr.ps.Src) 189 } 190 func (d *BuildNodeData) ChildInt(i int) (int, error) { 191 s := d.ChildStr(i) 192 v, err := strconv.ParseInt(s, 10, 64) 193 if err != nil { 194 return 0, err 195 } 196 return int(v), nil 197 } 198 func (d *BuildNodeData) ChildOptional(i int) (*BuildNodeData, bool) { 199 d2 := d.Child(i) 200 if d2.IsEmpty() { 201 return nil, false 202 } 203 return d2, true 204 } 205 206 func (d *BuildNodeData) IsOr(i int) bool { 207 or, ok := d.cpn.rule.(*OrRule) 208 if !ok { 209 return false 210 } 211 target := or.childs()[i] 212 213 switch t := target.(type) { 214 case *DefRule: 215 if len(d.cpn.childs) == 1 { 216 return d.cpn.childs[0].rule == t 217 } 218 default: 219 if len(d.cpn.childs) == len(target.childs()) { 220 for k, cpn := range d.cpn.childs { 221 if cpn.rule != target.childs()[k] { 222 return false 223 } 224 } 225 return true 226 } 227 } 228 return false 229 } 230 231 //---------- 232 233 func (d *BuildNodeData) ChildLoop(i int, fn BuildNodeFn) error { 234 d2 := d.Child(i) 235 //d2.PrintRuleTree(5) 236 if d2.IsEmpty() { 237 return nil 238 } 239 240 dr, ok := d2.cpn.rule.(*DefRule) 241 if !ok { 242 return fmt.Errorf("not a defrule") 243 } 244 245 vis := (BuildNodeFn)(nil) 246 vis = func(d3 *BuildNodeData) error { 247 if d3.IsEmpty() { 248 return nil 249 } 250 if err := vis(d3.Child(0)); err != nil { // loop child 251 return err 252 } 253 return fn(d3.Child(1)) // rule child 254 } 255 256 if dr.isPZeroOrMore { 257 return vis(d2) 258 } 259 if dr.isPOneOrMore { 260 if err := vis(d2.Child(0)); err != nil { 261 return err 262 } 263 return fn(d2.Child(1)) // rule child (last) 264 } 265 266 return fmt.Errorf("child not a loop (missing loop option)") 267 } 268 269 func (d *BuildNodeData) ChildLoop2(i int, loopi int, pre, post BuildNodeFn) error { 270 d2 := d.Child(i) 271 //d2.PrintRuleTree(5) 272 if d2.IsEmpty() { 273 return nil 274 } 275 276 vis := (BuildNodeFn)(nil) 277 vis = func(d3 *BuildNodeData) error { 278 if d3.IsEmpty() { 279 return nil 280 } 281 282 // could be a production with less childs 283 l := d3.ChildsLen() 284 if loopi >= l { 285 return nil 286 } 287 288 // rule 289 if pre != nil { 290 if err := pre(d3); err != nil { 291 return err 292 } 293 } 294 // loop 295 if err := vis(d3.Child(loopi)); err != nil { 296 return err 297 } 298 // rule 299 if post != nil { 300 if err := post(d3); err != nil { 301 return err 302 } 303 } 304 return nil 305 } 306 return vis(d2) 307 } 308 309 //---------- 310 //---------- 311 //---------- 312 313 // maxdepth=-1 will print all 314 func SprintNodeTree(src []byte, node PNode, maxDepth int) string { 315 sb := &strings.Builder{} 316 317 pr := func(depth int, f string, args ...interface{}) { 318 for i := 0; i < depth; i++ { 319 fmt.Fprint(sb, "\t") 320 } 321 fmt.Fprintf(sb, f, args...) 322 } 323 324 vis := (func(PNode, int))(nil) 325 vis = func(n PNode, depth int) { 326 if maxDepth >= 0 && depth >= maxDepth { 327 pr(depth, "-> ... (maxdepth=%v)\n", maxDepth) 328 return 329 } 330 331 tag := "" 332 333 cpn, ok := n.(*CPNode) 334 if ok { 335 tag = cpn.rule.id() 336 } else { 337 tag = fmt.Sprintf("%T", n) 338 } 339 340 pr(depth, "-> %v: %q\n", tag, PNodeString(n, src)) 341 342 if cpn != nil { 343 344 visitChilds := true 345 if dr, ok := cpn.rule.(*DefRule); ok { 346 if dr.isNoPrint { 347 visitChilds = false 348 } 349 } 350 351 if visitChilds { 352 for _, child := range cpn.childs { 353 vis(child, depth+1) 354 } 355 } 356 } 357 } 358 vis(node, 0) 359 return strings.TrimSpace(sb.String()) 360 }