1// Copyright 2011 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Parse nodes. 6package parse 7 8import "fmt" 9 10var textFormat = "%s" // Changed to "%q" in tests for better error messages. 11 12// A Node is an element in the parse tree. The interface is trivial. 13// The interface contains an unexported method so that only 14// types local to this package can satisfy it. 15type Node interface { 16 Type() NodeType 17 String() string 18 Position() Pos // byte position of start of node in full original input string 19 // Make sure only functions in this package can create Nodes. 20 unexported() 21} 22 23// NodeType identifies the type of a parse tree node. 24type NodeType int 25 26// Pos represents a byte position in the original input text from which 27// this template was parsed. 28type Pos int 29 30func (p Pos) Position() Pos { 31 return p 32} 33 34// unexported keeps Node implementations local to the package. 35// All implementations embed Pos, so this takes care of it. 36func (Pos) unexported() { 37} 38 39// Type returns itself and provides an easy default implementation 40// for embedding in a Node. Embedded in all non-trivial Nodes. 41func (t NodeType) Type() NodeType { 42 return t 43} 44 45const ( 46 NodeAsk NodeType = iota // key:value expression. 47 NodeBinary NodeType = iota // 48 NodeUnary NodeType = iota // 49) 50 51// BinaryNode holds two arguments and an operator. 52type BinaryNode struct { 53 NodeType 54 Pos 55 Args [2]Node 56 Operator item 57 OpStr string 58} 59 60func newBinary(operator item, arg1, arg2 Node) *BinaryNode { 61 return &BinaryNode{NodeType: NodeBinary, Pos: operator.pos, Args: [2]Node{arg1, arg2}, Operator: operator, OpStr: operator.val} 62} 63 64func (b *BinaryNode) String() string { 65 return fmt.Sprintf("%s %s %s", b.Args[0], b.Operator.val, b.Args[1]) 66} 67 68func (b *BinaryNode) StringAST() string { 69 return fmt.Sprintf("%s(%s, %s)", b.Operator.val, b.Args[0], b.Args[1]) 70} 71 72// UnaryNode holds one argument and an operator. 73type UnaryNode struct { 74 NodeType 75 Pos 76 Arg Node 77 Operator item 78 OpStr string 79} 80 81func newUnary(operator item, arg Node) *UnaryNode { 82 return &UnaryNode{NodeType: NodeUnary, Pos: operator.pos, Arg: arg, Operator: operator, OpStr: operator.val} 83} 84 85func (u *UnaryNode) String() string { 86 return fmt.Sprintf("%s%s", u.Operator.val, u.Arg) 87} 88 89func (u *UnaryNode) StringAST() string { 90 return fmt.Sprintf("%s(%s)", u.Operator.val, u.Arg) 91} 92 93// Walk invokes f on n and sub-nodes of n. 94func Walk(n Node, f func(Node)) { 95 f(n) 96 switch n := n.(type) { 97 case *BinaryNode: 98 Walk(n.Args[0], f) 99 Walk(n.Args[1], f) 100 case *AskNode: 101 // Ignore. 102 case *UnaryNode: 103 Walk(n.Arg, f) 104 default: 105 panic(fmt.Errorf("other type: %T", n)) 106 } 107} 108 109// AskNode holds a filter invocation. 110type AskNode struct { 111 NodeType 112 Pos 113 Text string 114} 115 116func (a *AskNode) String() string { 117 return fmt.Sprintf("%s", a.Text) 118} 119 120func newAsk(pos Pos, text string) *AskNode { 121 return &AskNode{ 122 NodeType: NodeAsk, 123 Pos: pos, 124 Text: text, 125 } 126}