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.