ast

package
v0.1.2 Latest Latest
Warning

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

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

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

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
	// Value is the expression to capture the value of the node.
	Value interface{}

	// Convert is an optional functions to change the type of the parsed value.
	// e.g. convert "1" to an integer instead of the string itself.
	Convert func(i string) 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

type Node

type Node struct {
	// Type of the node.
	Type int
	// Value of the node. Only possible if it has no children.
	Value interface{}

	// 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 (*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) 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

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 (*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{
		Type: 1,
		Value: parser.CheckRuneFunc(func(r rune) bool {
			return '0' <= r && r <= '9'
		}),
	}

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

[-01] [[001] 1, [001] 2] <nil>
Example (Capture)
package main

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

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

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

[000] 1 <nil>
<nil> <nil>
[000] 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"))

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

parse: expected op.Not {bar} but got "bar"
<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 (
		d    = ast.Capture{Value: 'd'}
		da   = ast.Capture{Value: "da"}
		data = ast.Capture{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{a}}))
}
Output:

[000] d <nil>
[000] at <nil>
<nil> parse: expected op.Or [{0 100 <nil>} {0 116 <nil>} {{0 97 <nil>}}] 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"
	"strconv"
)

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

[-01] [[000] 1, [000] 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{
		Value: op.Min(3, 'a'),
	})) // 3 * 'a'

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

[000] aaa <nil>
<nil> parse: expected op.Range {4 -1 97} 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: expected int32 100 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: expected int32 95 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 (
		d    = ast.Capture{Value: 'd'}
		da   = ast.Capture{Value: "da"}
		data = ast.Capture{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: expected op.XOr [{0 100 <nil>} {0 da <nil>} {0 data <nil>}] but got "da"
<nil> parse: expected op.XOr [{0 97 <nil>} {0 116 <nil>}] but got "d"

Jump to

Keyboard shortcuts

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