tree

package
v0.0.0-...-9e081f2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2024 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package tree provides basic functions for building, manipulating, and traversing syntax trees. A tree consists of linked node and token elements, the root is the initial node element.

Index

Examples

Constants

View Source
const (
	WalkerStop         = 1 << iota // Stop traversing.
	WalkerSkipChildren             // Skip traversing child subtrees of the last fetched element. Ignored if no elements fetched yet.
	WalkerSkipSiblings             // Skip sibling subtrees of the last fetched element. Ignored if no elements fetched yet.
)

Variables

This section is empty.

Functions

func AppendChild

func AppendChild(parent NodeElement, el Element)

AppendChild places new element as a child of target one. New element becomes target's last child.

func AppendSibling

func AppendSibling(prev, el Element)

AppendSibling places new element after target one. Target becomes new element's previous sibling, target's next sibling (if any) becomes new element's next sibling. Does nothing if either new or target element is nil.

func Detach

func Detach(n Element)

Detach removes element from tree. Parent and sibling references are removed, but descendants are kept. Does nothing if the element is the tree root.

func NodeHook

func NodeHook(node string, tok *lexer.Token, pc *parser.ParseContext) (parser.NodeHookInstance, error)

NodeHook implements parser.NodeHook and builds syntax tree. Intended to be used as node hook for parser.AnyNode.

func PrependSibling

func PrependSibling(next, el Element)

PrependSibling places new element before target one. Target becomes new element's next sibling, target's previous sibling (if any) becomes new element's previous sibling. Does nothing if either new or target element is nil.

func Replace

func Replace(old, n Element)

Replace replaces old element with new one or simply removes old element if the new one is nil.

func Walk

func Walk(root Element, mode WalkMode, visitor Visitor)

Walk traverses given subtree in specified order calling visitor for each fetched element.

Example
package main

import (
	"fmt"
	"github.com/ava12/llx/langdef"
	"github.com/ava12/llx/parser"
	"github.com/ava12/llx/tree"
)

func main() {
	input := "foo=bar"
	grammar := `$name = /\w+/; $op = /=/; g = var, "=", value; var = $name; value = $name;`
	g, e := langdef.ParseString("grammar", grammar)
	if e != nil {
		fmt.Println(e)
		return
	}

	p, _ := parser.New(g)
	h := parser.Hooks{Nodes: parser.NodeHooks{
		parser.AnyNode: tree.NodeHook,
	}}

	root, e := p.ParseString("input", input, &h)
	if e != nil {
		fmt.Println(e)
		return
	}

	indent := "----------"
	visitor := func(stat tree.WalkStat) tree.WalkerFlags {
		el := stat.Element
		if el.IsNode() {
			fmt.Printf("%s%s:\n", indent[:stat.Level*2], el.TypeName())
		} else {
			fmt.Printf("%s%s %q\n", indent[:stat.Level*2], el.TypeName(), el.Token().Text())
		}
		return 0
	}
	tree.Walk(root.(tree.Element), tree.WalkLtr, visitor)
}
Output:

g:
--var:
----name "foo"
--op "="
--value:
----name "bar"

Types

type Element

type Element interface {
	// IsNode returns true for node element, false for token element.
	IsNode() bool
	// TypeName returns token or node type name.
	TypeName() string
	// Token returns token for this element (for node it is initial token).
	Token() *lexer.Token
	// Parent returns parent node element, nil for tree root.
	Parent() NodeElement
	// Prev returns previous sibling for element, nil for first child or tree root.
	Prev() Element
	// Next returns the next sibling for element, nil for last child or tree root.
	Next() Element
	// SetParent sets parent node for element, nil to remove element from tree.
	// Used by SetChild and RemoveChild.
	SetParent(NodeElement)
	// SetPrev sets previous sibling for element, nil to make the first sibling or to remove element from tree.
	// Used by functions manipulating child and sibling elements.
	SetPrev(Element)
	// SetNext sets the next sibling for element, nil to make the last sibling or to remove element from tree.
	// Used by functions manipulating child and sibling elements.
	SetNext(Element)
}

Element represents parse tree element, either a node or a token.

func Ancestors

func Ancestors(el Element) []Element

Ancestors returns ancestors of given element in closest-to-farthest order, i.e. the first output element is given element's parent and the last one is the tree root.

func Children

func Children(n Element) []Element

Children returns child elements (if there are any) or nil if given element is not a node. Child elements are returned in left-to-right order.

func FirstTokenElement

func FirstTokenElement(n Element) Element

FirstTokenElement returns element itself if it's not a node or returns the first token element captured by node or its descendant nodes. Returns nil if neither node nor its descendants contain token elements.

func LastTokenElement

func LastTokenElement(n Element) Element

LastTokenElement returns element itself if it's not a node or returns the last token element captured by node or its descendant nodes. Returns nil if neither node nor its descendants contain token elements.

func NewTokenElement

func NewTokenElement(t *lexer.Token) Element

NewTokenElement creates token element for given token.

func NextSiblings

func NextSiblings(el Element) []Element

NextSiblings returns following siblings of given element in closest-to-farthest order, i.e. the first output element is given element's next sibling and the last one is the last sibling.

func NextTokenElement

func NextTokenElement(n Element) Element

NextTokenElement returns the first token element after given one, if there are any. I.e. the first token element in the next sibling or its parent's next sibling etc.

func PrevSiblings

func PrevSiblings(el Element) []Element

PrevSiblings returns preceding siblings of given element in closest-to-farthest order, i.e. the first output element is given element's previous sibling and the last one is the first sibling.

func PrevTokenElement

func PrevTokenElement(n Element) Element

PrevTokenElement returns the last token element before given one, if there are any. I.e. the last token element in the previous sibling or its parent's previous sibling etc.

type Extractor

type Extractor func(n Element) []Element

Extractor returns a list of elements related to given non-nil element. Result must not contain nil elements.

func All

func All(nes ...Extractor) Extractor

All creates extractor that applies all given extractors to input element. Returns merged outputs, may contain duplicate elements.

func Any

func Any(nes ...Extractor) Extractor

Any creates extractor that applies given extractors to input element in order until it gets non-empty output. Returns first non-empty output or nil if all outputs were empty.

func Nth

func Nth(ex Extractor, indexes ...int) Extractor

Nth creates extractor that applies given extractor to input element and returns output elements with given indexes (if present).

type Filter

type Filter func(n Element) bool

Filter examines given non-nil element and decides whether it is accepted and must be kept in element list (true) or rejected and must be removed from list (false).

func IsA

func IsA(names ...string) Filter

IsA creates filter that accepts elements with given type names and rejects others.

func IsALiteral

func IsALiteral(texts ...string) Filter

IsALiteral creates filter that accepts token elements with given content and rejects others.

func IsAll

func IsAll(fs ...Filter) Filter

IsAll creates filter that accepts element if it is accepted by all of given filters and rejects otherwise.

func IsAny

func IsAny(fs ...Filter) Filter

IsAny creates filter that accepts element if it is accepted by any of given filters and rejects otherwise.

func IsNot

func IsNot(f Filter) Filter

IsNot creates filter that inverts result of given filter (i.e. rejects accepted element and accepts rejected).

type HookInstance

type HookInstance struct {
	// contains filtered or unexported fields
}

func NewHookInstance

func NewHookInstance(typeName string, tok *lexer.Token) *HookInstance

func (*HookInstance) EndNode

func (hi *HookInstance) EndNode() (result interface{}, e error)

func (*HookInstance) HandleNode

func (hi *HookInstance) HandleNode(name string, result interface{}) error

func (*HookInstance) HandleToken

func (hi *HookInstance) HandleToken(token *lexer.Token) error

func (*HookInstance) NewNode

func (hi *HookInstance) NewNode(node string, token *lexer.Token) error

type NodeElement

type NodeElement interface {
	Element
	// FirstChild returns first child element or nil if there are no children.
	FirstChild() Element
	// LastChild returns last child element or nil if there are no children.
	LastChild() Element
	// AddChild inserts child element. New child is placed before given one or after the last child.
	// Does nothing if n is nil or given element does not belong to node.
	AddChild(n, before Element)
	// RemoveChild detaches given child element from node.
	// Does nothing if given element is not this node's child.
	RemoveChild(Element)
}

NodeElement represents parse tree node.

func NewNodeElement

func NewNodeElement(typeName string, tok *lexer.Token) NodeElement

NewNodeElement creates node element of given type with given initial token, token may be nil.

type Selector

type Selector struct {
	// contains filtered or unexported fields
}

Selector transforms list of elements to another list using provided transformers (extractors and filters). Contains list of transformers, configurable and reusable.

func NewSelector

func NewSelector() *Selector

NewSelector creates selector with empty list of transformers.

func (*Selector) Apply

func (s *Selector) Apply(input ...Element) []Element

Apply applies stored list of transformers to passed list of elements and returns output. Transformers are used in FIFO order, output is used as an input for the next transformer.

func (*Selector) DeepSearch

func (s *Selector) DeepSearch(nf Filter) *Selector

DeepSearch adds transformer that treats input element as a subtree root and traverses this subtree extracting elements that are accepted by given filter. Extracted elements are also traversed, so if accepted element contains acceptable descendants, those descendants will be output as well. Modifies selector, chainable.

func (*Selector) Extract

func (s *Selector) Extract(ex Extractor) *Selector

Extract adds extractor to transformer list. Modifies selector, chainable.

func (*Selector) Filter

func (s *Selector) Filter(nf Filter) *Selector

Filter adds filter to transformer list. Modifies selector, chainable.

func (*Selector) Search

func (s *Selector) Search(nf Filter) *Selector

Search adds transformer that treats input element as a subtree root and traverses this subtree extracting elements that are accepted by given filter. Extracted elements are not traversed, so if accepted element contains acceptable descendants, those descendants will not be output. Modifies selector, chainable.

func (*Selector) Unique

func (s *Selector) Unique() *Selector

Unique instructs selector to remove duplicated elements from output of Apply method, by default output is returned as is. Modifies selector, chainable.

type Visitor

type Visitor func(s WalkStat) WalkerFlags

Visitor processes element fetched by walker and responds which parts of subtree must be skipped on next step.

type WalkMode

type WalkMode int

WalkMode defines subtree traversing mode.

const (
	WalkLtr WalkMode = 0 // Left to right, parent first, depth-first.
	WalkRtl WalkMode = 1 // Right to left, parent first, depth-first.
)

type WalkStat

type WalkStat struct {
	// Element is the fetched element. nil if subtree traversal is finished.
	Element Element
	// Level is the nest level of fetched element relative to subtree root.
	// 0 is root, 1 is root's child etc.
	Level int
}

WalkStat contains information about fetched subtree element.

type Walker

type Walker struct {
	// contains filtered or unexported fields
}

Walker traverses given subtree in specified order. References given subtree, not reusable. Subtree should not be modified while walker is in use.

func NewWalker

func NewWalker(root Element, m WalkMode) *Walker

NewWalker creates walker for given subtree.

func (*Walker) Next

func (w *Walker) Next() WalkStat

Next returns next element, same as Step(0).

func (*Walker) Step

func (w *Walker) Step(f WalkerFlags) (stat WalkStat)

Step returns the next element omitting specified parts of subtree. Result.Element is nil if WalkerStop is passed or traversal is finished. When this method returns nil all future calls wil return nil.

func (*Walker) Walk

func (w *Walker) Walk(visitor Visitor)

Walk traverses subtree using Step(). Visitor is called for each fetched element.

type WalkerFlags

type WalkerFlags = int

WalkerFlags instruct walker which parts of subtree must be skipped.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL