Documentation
¶
Index ¶
- Constants
- Variables
- func ConvertAliases(i interface{}) interface{}
- type Capture
- type LoopUp
- type LoopUpError
- type Node
- func (n *Node) Adopt(other *Node)
- func (n *Node) Children() []*Node
- func (n *Node) IsParent() bool
- func (n *Node) MarshalJSON() ([]byte, error)
- func (n *Node) MarshalJSONString() (string, error)
- func (n *Node) Remove() *Node
- func (n *Node) SetFirst(child *Node)
- func (n *Node) SetLast(child *Node)
- func (n *Node) SetNext(sibling *Node)
- func (n *Node) SetPrevious(sibling *Node)
- func (n Node) String() string
- func (n *Node) TypeString() string
- func (n *Node) UnmarshalJSON(bytes []byte) error
- type ParseNode
- type Parser
Examples ¶
Constants ¶
const ( Unknown = iota // PEGN-AST (github.com/di-wu/parser) NodeType // 001 LiteralType // 002 ChildrenType // 003 IntegerType // 004 )
Node Types
Variables ¶
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
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 (*Node) IsParent ¶
IsParent returns whether the node has children and thus is not a value node.
func (*Node) MarshalJSON ¶ added in v0.2.0
func (*Node) MarshalJSONString ¶ added in v0.2.0
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) SetPrevious ¶
SetPrevious inserts the given node as the previous sibling.
func (*Node) TypeString ¶ added in v0.2.0
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
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 Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser represents a general purpose AST parser.
func NewFromParser ¶ added in v0.1.5
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 ¶
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
SetOperator allows you to support additional (prioritized) operators. Should return an UnsupportedType error if the given value is not supported.