ast

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2021 License: Apache-2.0 Imports: 4 Imported by: 9

Documentation

Index

Examples

Constants

View Source
const (
	Unknown = iota

	// PEGN-AST (github.com/di-wu/parser)
	NodeType     // 001
	LiteralType  // 002
	ChildrenType // 003
	IntegerType  // 004
)

Node Types

Variables

View Source
var NodeTypes = []string{
	"UNKNOWN",

	"Node",
	"Literal",
	"Children",
	"Integer",
}

Functions

func ConvertAliases

func ConvertAliases(i interface{}) interface{}

ConvertAliases converts various default primitive types to aliases for type matching.

Types

type Capture

type Capture struct {
	// Type of the node.
	Type int
	// TypeStrings contains all the string representations of the available types.
	TypeStrings []string
	// Value is the expression to capture the value of the node.
	Value interface{}
}

Capture is a structure to indicate that the value should be converted to a node. If one of the children returns a node, then that node gets returned

func (Capture) String added in v0.2.0

func (c Capture) String() string

type LoopUp added in v0.1.5

type LoopUp struct {
	Key   string
	Table *map[string]interface{}
}

LoopUp allows for circular references to be used.

func (*LoopUp) Get added in v0.1.5

func (l *LoopUp) Get() (interface{}, error)

type LoopUpError added in v0.1.5

type LoopUpError struct {
	Value LoopUp
}

LoopUpError is an error that occurs when a key can not be found in the table.

func (*LoopUpError) Error added in v0.1.5

func (e *LoopUpError) Error() string

type Node

type Node struct {
	// Type of the node.
	Type int
	// TypeStrings contains all the string representations of the available types.
	TypeStrings []string
	// Value of the node. Only possible if it has no children.
	Value string

	// Parent is the parent node.
	Parent *Node
	// PreviousSibling is the previous sibling of the node.
	PreviousSibling *Node
	// NextSibling is the next sibling of the node.
	NextSibling *Node
	// FirstChild is the first child of the node.
	FirstChild *Node
	// LastChild is the last child of the node.
	LastChild *Node
}

Node is a simple node in a tree with double linked lists instead of slices to keep track of its siblings and children. A node is either a value or a parent node.

func Parse added in v0.3.0

func Parse(data []byte, node ParseNode) (*Node, error)

Parse parses the given data based on the parse node.

func (*Node) Adopt

func (n *Node) Adopt(other *Node)

func (*Node) Children

func (n *Node) Children() []*Node

Children returns all the children of the node.

func (*Node) IsParent

func (n *Node) IsParent() bool

IsParent returns whether the node has children and thus is not a value node.

func (*Node) MarshalJSON added in v0.2.0

func (n *Node) MarshalJSON() ([]byte, error)

func (*Node) MarshalJSONString added in v0.2.0

func (n *Node) MarshalJSONString() (string, error)
Example
typeStrings := []string{"A", "NL"}
p, _ := New([]byte("aaaaa\n"))
n, _ := p.Expect(op.And{
	op.MinOne(Capture{
		Type:        0,
		TypeStrings: typeStrings,
		Value:       'a',
	}),
	Capture{
		Type:        1,
		TypeStrings: typeStrings,
		Value:       '\n',
	},
})
fmt.Println(n.MarshalJSONString())
Output:

[-1,[[0,"a"],[0,"a"],[0,"a"],[0,"a"],[0,"a"],[1,"\n"]]] <nil>

func (*Node) Remove

func (n *Node) Remove() *Node

Remove removes itself from the tree.

func (*Node) SetFirst

func (n *Node) SetFirst(child *Node)

SetFirst inserts the given node as the first child of the node.

func (*Node) SetLast

func (n *Node) SetLast(child *Node)

SetLast inserts the given node as the last child of the node.

func (*Node) SetNext

func (n *Node) SetNext(sibling *Node)

SetNext inserts the given node as the next sibling.

func (*Node) SetPrevious

func (n *Node) SetPrevious(sibling *Node)

SetPrevious inserts the given node as the previous sibling.

func (Node) String

func (n Node) String() string

func (*Node) TypeString added in v0.2.0

func (n *Node) TypeString() string

TypeString returns the strings representation of the type. Same as TypeStrings[Type]. Returns "UNKNOWN" if not string representation is found or len(TypeStrings) == 0.

func (*Node) UnmarshalJSON added in v0.2.0

func (n *Node) UnmarshalJSON(bytes []byte) error
Example
node := Node{TypeStrings: []string{"A", "NL"}}
_ = node.UnmarshalJSON([]byte("[-1,[[0,\"a\"],[0,\"a\"],[0,\"a\"],[0,\"a\"],[0,\"a\"],[1,\"\\n\"]]]"))
fmt.Println(node.MarshalJSONString())
Output:

[-1,[[0,"a"],[0,"a"],[0,"a"],[0,"a"],[0,"a"],[1,"\\n"]]] <nil>

type ParseNode

type ParseNode func(p *Parser) (*Node, error)

ParseNode represents a function to parse ast nodes.

type Parser

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

Parser represents a general purpose AST parser.

func New

func New(input []byte) (*Parser, error)

New creates a new Parser.

func NewFromParser added in v0.1.5

func NewFromParser(p *parser.Parser) (*Parser, error)

NewFromParser creates a new Parser from a parser.Parser. This allows you to customize the internal parser. If no customization is needed, use New.

func (*Parser) Expect

func (ap *Parser) Expect(i interface{}) (*Node, error)

Expect checks whether the buffer contains the given value.

Example (And)
package main

import (
	"fmt"
	"github.com/di-wu/parser"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("1 <= 2"))
	digit := ast.Capture{
		TypeStrings: []string{"Digit"},
		Value: parser.CheckRuneFunc(func(r rune) bool {
			return '0' <= r && r <= '9'
		}),
	}

	fmt.Println(p.Expect(op.And{
		digit, parser.CheckString(" <= "), digit,
	}))
}
Output:

["UNKNOWN",[["Digit","1"],["Digit","2"]]] <nil>
Example (Capture)
package main

import (
	"fmt"
	"github.com/di-wu/parser"
	"github.com/di-wu/parser/ast"
)

func main() {
	p, _ := ast.New([]byte("1 <= 2"))
	digit := ast.Capture{
		TypeStrings: []string{"Digit"},
		Value: parser.CheckRuneFunc(func(r rune) bool {
			return '0' <= r && r <= '9'
		}),
	}
	lt := parser.CheckString(" <= ")

	fmt.Println(p.Expect(digit))
	fmt.Println(p.Expect(lt))
	fmt.Println(p.Expect(digit))
}
Output:

["Digit","1"] <nil>
<nil> <nil>
["Digit","2"] <nil>
Example (Class)
package main

import (
	"fmt"
	"github.com/di-wu/parser"
	"github.com/di-wu/parser/ast"
)

func main() {
	p, _ := ast.New([]byte("1 <= 2"))
	digit := func(p *parser.Parser) (*parser.Cursor, bool) {
		r := p.Current()
		return p.Mark(), '0' <= r && r <= '9'
	}
	lt := func(p *parser.Parser) (*parser.Cursor, bool) {
		var last *parser.Cursor
		for _, r := range []rune("<=") {
			if p.Current() != r {
				return nil, false
			}
			last = p.Mark()
			p.Next()
		}
		return last, true
	}

	fmt.Println(p.Expect(digit))
	_, _ = p.Expect(' ') // Skip space.
	fmt.Println(p.Expect(lt))
	_, _ = p.Expect(' ') // Skip space.
	fmt.Println(p.Expect(digit))
}
Output:

<nil> <nil>
<nil> <nil>
<nil> <nil>
Example (Not)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("bar"))

	fmt.Println(p.Expect(op.Not{Value: "bar"}))
	fmt.Println(p.Expect(op.Not{
		Value: ast.Capture{
			Value: "baz",
		},
	}))
}
Output:

<nil> parse conflict [00:003]: expected op.Not !"bar" but got "bar"
<nil> <nil>
Example (Or)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("data"))

	var (
		types = []string{
			"d", "da", "data",
		}

		d = ast.Capture{
			Type:        0,
			TypeStrings: types,
			Value:       'd',
		}
		da = ast.Capture{
			Type:        1,
			TypeStrings: types,
			Value:       "da",
		}
		data = ast.Capture{
			Type:        2,
			TypeStrings: types,
			Value:       "data",
		}
		a   = ast.Capture{Value: 'a'}
		at  = ast.Capture{Value: "at"}
		ata = ast.Capture{Value: "ata"}
		t   = ast.Capture{Value: 't'}
	)

	fmt.Println(p.Expect(op.Or{d, da, data}))
	fmt.Println(p.Expect(op.Or{at, a, ata}))
	fmt.Println(p.Expect(op.Or{d, t, op.Not{Value: a}}))
}
Output:

["d","d"] <nil>
["UNKNOWN","at"] <nil>
<nil> parse conflict [00:004]: expected op.Or or[d {000} !{000}] but got 'a'
Example (Parse_node)
package main

import (
	"fmt"
	"github.com/di-wu/parser"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("1 <= 2"))
	fmt.Println(p.Expect(func(p *ast.Parser) (*ast.Node, error) {
		digit := ast.Capture{
			TypeStrings: []string{"Digit"},
			Value: parser.CheckRuneFunc(func(r rune) bool {
				return '0' <= r && r <= '9'
			}),
		}
		return p.Expect(op.And{digit, parser.CheckString(" <= "), digit})
	}))
}
Output:

["UNKNOWN",[["Digit","1"],["Digit","2"]]] <nil>
Example (Range)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("aaa"))
	fmt.Println(p.Expect(ast.Capture{
		TypeStrings: []string{"3A"},
		Value:       op.Min(3, 'a'),
	})) // 3 * 'a'

	p, _ = ast.New([]byte("aaa"))
	fmt.Println(p.Expect(op.Min(4, 'a'))) // err
}
Output:

["3A","aaa"] <nil>
<nil> parse conflict [00:003]: expected op.Range 'a'{4:-1} but got "aaa"
Example (Rune)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
)

func main() {
	p, _ := ast.New([]byte("data"))

	fmt.Println(p.Expect('d'))
	fmt.Println(p.Expect('d')) // Invalid.
	fmt.Println(p.Expect('a'))
	fmt.Println(p.Expect('t'))
	fmt.Println(p.Expect('a'))
}
Output:

<nil> <nil>
<nil> parse conflict [00:001]: expected int32 'd' but got 'a'
<nil> <nil>
<nil> <nil>
<nil> <nil>
Example (String)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
)

func main() {
	p, _ := ast.New([]byte("some data"))

	fmt.Println(p.Expect("some"))
	fmt.Println(p.Expect('_'))
	_, _ = p.Expect(' ') // Skip space.
	fmt.Println(p.Expect("data"))
}
Output:

<nil> <nil>
<nil> parse conflict [00:004]: expected int32 '_' but got ' '
<nil> <nil>
Example (Xor)
package main

import (
	"fmt"
	"github.com/di-wu/parser/ast"
	"github.com/di-wu/parser/op"
)

func main() {
	p, _ := ast.New([]byte("data"))

	var (
		types = []string{
			"d", "da", "data",
		}

		d = ast.Capture{
			Type:        0,
			TypeStrings: types,
			Value:       'd',
		}
		da = ast.Capture{
			Type:        1,
			TypeStrings: types,
			Value:       "da",
		}
		data = ast.Capture{
			Type:        2,
			TypeStrings: types,
			Value:       "data",
		}
		a = ast.Capture{Value: 'a'}
		t = ast.Capture{Value: 't'}
	)

	fmt.Println(p.Expect(op.XOr{d, da, data}))
	fmt.Println(p.Expect(op.XOr{a, t}))
}
Output:

<nil> parse conflict [00:001]: expected op.XOr xor[d da data] but got "da"
<nil> parse conflict [00:000]: expected op.XOr xor[{000} {000}] but got 'd'

func (*Parser) SetConverter added in v0.1.5

func (ap *Parser) SetConverter(c func(i interface{}) interface{})

SetConverter allows you to add additional (prioritized) converters to the parser. e.g. convert aliases to other types or overwrite defaults.

func (*Parser) SetOperator added in v0.1.5

func (ap *Parser) SetOperator(o func(i interface{}) (*Node, error))

SetOperator allows you to support additional (prioritized) operators. Should return an UnsupportedType error if the given value is not supported.

Jump to

Keyboard shortcuts

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