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  }