func NewDoNode(expr Expr, pos Pos) *DoNode {
	return &DoNode{pos, TrimmableNode{}, expr}
}
NewDoNode returns a DoNode.
package parse
import (
	"fmt"
	"sort"
	"strings"
)
type Node interface {
	String() string  
	Start() Pos      
	All() []Node     
}
type TrimmableNode struct {
	TrimBefore bool  
	TrimAfter  bool  
}
type Pos struct {
	Line   int
	Offset int
}
func (p Pos) Start() Pos {
	return p
}
func (p Pos) String() string {
	return fmt.Sprintf("%d:%d", p.Line, p.Offset)
}
type ModuleNode struct {
	*BodyNode
	Parent *ExtendsNode  
	Origin string        
}
func NewModuleNode(name string, nodes ...Node) *ModuleNode {
	return &ModuleNode{NewBodyNode(Pos{1, 0}, nodes...), nil, name}
}
func (l *ModuleNode) String() string {
	return fmt.Sprintf("Module%s", l.Nodes)
}
type BodyNode struct {
	Pos
	Nodes []Node
}
func NewBodyNode(pos Pos, nodes ...Node) *BodyNode {
	return &BodyNode{pos, nodes}
}
func (l *BodyNode) Append(n Node) {
	l.Nodes = append(l.Nodes, n)
}
func (l *BodyNode) String() string {
	return fmt.Sprintf("Body%s", l.Nodes)
}
func (l *BodyNode) All() []Node {
	return l.Nodes
}
type TextNode struct {
	Pos
	Data string  
}
func NewTextNode(data string, p Pos) *TextNode {
	return &TextNode{p, data}
}
func (t *TextNode) String() string {
	return fmt.Sprintf("Text(%s)", t.Data)
}
func (t *TextNode) All() []Node {
	return []Node{}
}
type CommentNode struct {
	*TextNode
	TrimmableNode
}
func NewCommentNode(data string, p Pos) *CommentNode {
	return &CommentNode{NewTextNode(data, p), TrimmableNode{}}
}
type PrintNode struct {
	Pos
	TrimmableNode
	X Expr  
}
func NewPrintNode(exp Expr, p Pos) *PrintNode {
	return &PrintNode{p, TrimmableNode{}, exp}
}
func (t *PrintNode) String() string {
	return fmt.Sprintf("Print(%s)", t.X)
}
func (t *PrintNode) All() []Node {
	return []Node{t.X}
}
type BlockNode struct {
	Pos
	TrimmableNode
	Name   string  
	Body   Node    
	Origin string  
}
func NewBlockNode(name string, body Node, p Pos) *BlockNode {
	return &BlockNode{p, TrimmableNode{}, name, body, ""}
}
func (t *BlockNode) String() string {
	return fmt.Sprintf("Block(%s: %s)", t.Name, t.Body)
}
func (t *BlockNode) All() []Node {
	return []Node{t.Body}
}
type IfNode struct {
	Pos
	TrimmableNode
	Cond Expr  
	Body Node  
	Else Node  
}
func NewIfNode(cond Expr, body Node, els Node, p Pos) *IfNode {
	return &IfNode{p, TrimmableNode{}, cond, body, els}
}
func (t *IfNode) String() string {
	return fmt.Sprintf("If(%s: %s Else: %s)", t.Cond, t.Body, t.Else)
}
func (t *IfNode) All() []Node {
	return []Node{t.Cond, t.Body, t.Else}
}
type ExtendsNode struct {
	Pos
	TrimmableNode
	Tpl Expr  
}
func NewExtendsNode(tplRef Expr, p Pos) *ExtendsNode {
	return &ExtendsNode{p, TrimmableNode{}, tplRef}
}
func (t *ExtendsNode) String() string {
	return fmt.Sprintf("Extends(%s)", t.Tpl)
}
func (t *ExtendsNode) All() []Node {
	return []Node{t.Tpl}
}
type ForNode struct {
	Pos
	TrimmableNode
	Key  string  
	Val  string  
	X    Expr    
	Body Node    
	Else Node    
}
func NewForNode(k, v string, expr Expr, body, els Node, p Pos) *ForNode {
	return &ForNode{p, TrimmableNode{}, k, v, expr, body, els}
}
func (t *ForNode) String() string {
	return fmt.Sprintf("For(%s, %s in %s: %s else %s)", t.Key, t.Val, t.X, t.Body, t.Else)
}
func (t *ForNode) All() []Node {
	return []Node{t.X, t.Body, t.Else}
}
type IncludeNode struct {
	Pos
	TrimmableNode
	Tpl  Expr  
	With Expr  
	Only bool  
}
func NewIncludeNode(tmpl Expr, with Expr, only bool, pos Pos) *IncludeNode {
	return &IncludeNode{pos, TrimmableNode{}, tmpl, with, only}
}
func (t *IncludeNode) String() string {
	return fmt.Sprintf("Include(%s with %s %v)", t.Tpl, t.With, t.Only)
}
func (t *IncludeNode) All() []Node {
	return []Node{t.Tpl, t.With}
}
type EmbedNode struct {
	*IncludeNode
	Blocks map[string]*BlockNode  
}
func NewEmbedNode(tmpl Expr, with Expr, only bool, blocks map[string]*BlockNode, pos Pos) *EmbedNode {
	return &EmbedNode{NewIncludeNode(tmpl, with, only, pos), blocks}
}
func (t *EmbedNode) String() string {
	return fmt.Sprintf("Embed(%s with %s %v: %v)", t.Tpl, t.With, t.Only, t.Blocks)
}
func (t *EmbedNode) All() []Node {
	r := t.IncludeNode.All()
	for _, blk := range t.Blocks {
		r = append(r, blk)
	}
	return r
}
type UseNode struct {
	Pos
	TrimmableNode
	Tpl     Expr               
	Aliases map[string]string  
}
func NewUseNode(tpl Expr, aliases map[string]string, pos Pos) *UseNode {
	return &UseNode{pos, TrimmableNode{}, tpl, aliases}
}
func (t *UseNode) String() string {
	if l := len(t.Aliases); l > 0 {
		keys := make([]string, l)
		i := 0
		for orig := range t.Aliases {
			keys[i] = orig
			i++
		}
		sort.Strings(keys)
		res := make([]string, l)
		for i, orig := range keys {
			res[i] = orig + ": " + t.Aliases[orig]
		}
		return fmt.Sprintf("Use(%s with %s)", t.Tpl, strings.Join(res, ", "))
	}
	return fmt.Sprintf("Use(%s)", t.Tpl)
}
func (t *UseNode) All() []Node {
	return []Node{t.Tpl}
}
type SetNode struct {
	Pos
	TrimmableNode
	Name string  
	X    Expr    
}
func NewSetNode(varName string, expr Expr, pos Pos) *SetNode {
	return &SetNode{pos, TrimmableNode{}, varName, expr}
}
func (t *SetNode) String() string {
	return fmt.Sprintf("Set(%s = %v)", t.Name, t.X)
}
func (t *SetNode) All() []Node {
	return []Node{t.X}
}
type DoNode struct {
	Pos
	TrimmableNode
	X Expr  
}