func NewHashPair(pos int, line int) *HashPair {
	return &HashPair{
		NodeType: NodeHashPair,
		Loc:      Loc{pos, line},
	}
}
NewHashPair instanciates a new hash pair node.
package ast
import (
	"fmt"
	"strconv"
)
type Node interface {
	Type() NodeType
	Location() Loc
	String() string
	Accept(Visitor) interface{}
}
type Visitor interface {
	VisitProgram(*Program) interface{}
	VisitMustache(*MustacheStatement) interface{}
	VisitBlock(*BlockStatement) interface{}
	VisitPartial(*PartialStatement) interface{}
	VisitContent(*ContentStatement) interface{}
	VisitComment(*CommentStatement) interface{}
	VisitExpression(*Expression) interface{}
	VisitSubExpression(*SubExpression) interface{}
	VisitPath(*PathExpression) interface{}
	VisitString(*StringLiteral) interface{}
	VisitBoolean(*BooleanLiteral) interface{}
	VisitNumber(*NumberLiteral) interface{}
	VisitHash(*Hash) interface{}
	VisitHashPair(*HashPair) interface{}
}
type NodeType int
func (t NodeType) Type() NodeType {
	return t
}
const (
	NodeProgram NodeType = iota
	NodeMustache
	NodeBlock
	NodePartial
	NodeContent
	NodeComment
	NodeExpression
	NodeSubExpression
	NodePath
	NodeBoolean
	NodeNumber
	NodeString
	NodeHash
	NodeHashPair
)
type Loc struct {
	Pos  int  
	Line int  
}
func (l Loc) Location() Loc {
	return l
}
type Strip struct {
	Open  bool
	Close bool
	OpenStandalone   bool
	CloseStandalone  bool
	InlineStandalone bool
}
func NewStrip(openStr, closeStr string) *Strip {
	return &Strip{
		Open:  (len(openStr) > 2) && openStr[2] == '~',
		Close: (len(closeStr) > 2) && closeStr[len(closeStr)-3] == '~',
	}
}
func NewStripForStr(str string) *Strip {
	return &Strip{
		Open:  (len(str) > 2) && str[2] == '~',
		Close: (len(str) > 2) && str[len(str)-3] == '~',
	}
}
func (s *Strip) String() string {
	return fmt.Sprintf("Open: %t, Close: %t, OpenStandalone: %t, CloseStandalone: %t, InlineStandalone: %t", s.Open, s.Close, s.OpenStandalone, s.CloseStandalone, s.InlineStandalone)
}
type Program struct {
	NodeType
	Loc
	Body        []Node  
	BlockParams []string
	Chained     bool
	Strip *Strip
}
func NewProgram(pos int, line int) *Program {
	return &Program{
		NodeType: NodeProgram,
		Loc:      Loc{pos, line},
	}
}
func (node *Program) String() string {
	return fmt.Sprintf("Program{Pos: %d}", node.Loc.Pos)
}
func (node *Program) Accept(visitor Visitor) interface{} {
	return visitor.VisitProgram(node)
}
func (node *Program) AddStatement(statement Node) {
	node.Body = append(node.Body, statement)
}
type MustacheStatement struct {
	NodeType
	Loc
	Unescaped  bool
	Expression *Expression
	Strip *Strip
}
func NewMustacheStatement(pos int, line int, unescaped bool) *MustacheStatement {
	return &MustacheStatement{
		NodeType:  NodeMustache,
		Loc:       Loc{pos, line},
		Unescaped: unescaped,
	}
}
func (node *MustacheStatement) String() string {
	return fmt.Sprintf("Mustache{Pos: %d}", node.Loc.Pos)
}
func (node *MustacheStatement) Accept(visitor Visitor) interface{} {
	return visitor.VisitMustache(node)
}
type BlockStatement struct {
	NodeType
	Loc
	Expression *Expression
	Program *Program
	Inverse *Program
	OpenStrip    *Strip
	InverseStrip *Strip
	CloseStrip   *Strip
}
func NewBlockStatement(pos int, line int) *BlockStatement {
	return &BlockStatement{
		NodeType: NodeBlock,
		Loc:      Loc{pos, line},
	}
}
func (node *BlockStatement) String() string {
	return fmt.Sprintf("Block{Pos: %d}", node.Loc.Pos)
}
func (node *BlockStatement) Accept(visitor Visitor) interface{} {
	return visitor.VisitBlock(node)
}
type PartialStatement struct {
	NodeType
	Loc
	Name   Node    
	Params []Node  
	Hash   *Hash
	Strip  *Strip
	Indent string
}
func NewPartialStatement(pos int, line int) *PartialStatement {
	return &PartialStatement{
		NodeType: NodePartial,
		Loc:      Loc{pos, line},
	}
}
func (node *PartialStatement) String() string {
	return fmt.Sprintf("Partial{Name:%s, Pos:%d}", node.Name, node.Loc.Pos)
}
func (node *PartialStatement) Accept(visitor Visitor) interface{} {
	return visitor.VisitPartial(node)
}
type ContentStatement struct {
	NodeType
	Loc
	Value    string
	Original string
	RightStripped bool
	LeftStripped  bool
}
func NewContentStatement(pos int, line int, val string) *ContentStatement {
	return &ContentStatement{
		NodeType: NodeContent,
		Loc:      Loc{pos, line},
		Value:    val,
		Original: val,
	}
}
func (node *ContentStatement) String() string {
	return fmt.Sprintf("Content{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
}
func (node *ContentStatement) Accept(visitor Visitor) interface{} {
	return visitor.VisitContent(node)
}
type CommentStatement struct {
	NodeType
	Loc
	Value string
	Strip *Strip
}
func NewCommentStatement(pos int, line int, val string) *CommentStatement {
	return &CommentStatement{
		NodeType: NodeComment,
		Loc:      Loc{pos, line},
		Value: val,
	}
}
func (node *CommentStatement) String() string {
	return fmt.Sprintf("Comment{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
}
func (node *CommentStatement) Accept(visitor Visitor) interface{} {
	return visitor.VisitComment(node)
}
type Expression struct {
	NodeType
	Loc
	Path   Node    
	Params []Node  
	Hash   *Hash
}
func NewExpression(pos int, line int) *Expression {
	return &Expression{
		NodeType: NodeExpression,
		Loc:      Loc{pos, line},
	}
}
func (node *Expression) String() string {
	return fmt.Sprintf("Expr{Path:%s, Pos:%d}", node.Path, node.Loc.Pos)
}
func (node *Expression) Accept(visitor Visitor) interface{} {
	return visitor.VisitExpression(node)
}
func (node *Expression) HelperName() string {
	path, ok := node.Path.(*PathExpression)
	if !ok {
		return ""
	}
	if path.Data || (len(path.Parts) != 1) || (path.Depth > 0) || path.Scoped {
		return ""
	}
	return path.Parts[0]
}
func (node *Expression) FieldPath() *PathExpression {
	path, ok := node.Path.(*PathExpression)
	if !ok {
		return nil
	}
	return path
}
func (node *Expression) LiteralStr() (string, bool) {
	return LiteralStr(node.Path)
}
func (node *Expression) Canonical() string {
	if str, ok := HelperNameStr(node.Path); ok {
		return str
	}
	return ""
}
func HelperNameStr(node Node) (string, bool) {
	if str, ok := PathExpressionStr(node); ok {
		return str, ok
	}
	if str, ok := LiteralStr(node); ok {
		return str, ok
	}
	return "", false
}
func PathExpressionStr(node Node) (string, bool) {
	if path, ok := node.(*PathExpression); ok {
		result := path.Original
		if (len(result) >= 2) && (result[0] == '[') && (result[len(result)-1] == ']') {
			result = result[1 : len(result)-1]
		}
		return result, true
	}
	return "", false
}
func LiteralStr(node Node) (string, bool) {
	if lit, ok := node.(*StringLiteral); ok {
		return lit.Value, true
	}
	if lit, ok := node.(*BooleanLiteral); ok {
		return lit.Canonical(), true
	}
	if lit, ok := node.(*NumberLiteral); ok {
		return lit.Canonical(), true
	}
	return "", false
}
type SubExpression struct {
	NodeType
	Loc
	Expression *Expression
}
func NewSubExpression(pos int, line int) *SubExpression {
	return &SubExpression{
		NodeType: NodeSubExpression,
		Loc:      Loc{pos, line},
	}
}
func (node *SubExpression) String() string {
	return fmt.Sprintf("Sexp{Path:%s, Pos:%d}", node.Expression.Path, node.Loc.Pos)
}
func (node *SubExpression) Accept(visitor Visitor) interface{} {
	return visitor.VisitSubExpression(node)
}
type PathExpression struct {
	NodeType
	Loc
	Original string
	Depth    int
	Parts    []string
	Data     bool
	Scoped   bool
}
func NewPathExpression(pos int, line int, data bool) *PathExpression {
	result := &PathExpression{
		NodeType: NodePath,
		Loc:      Loc{pos, line},
		Data: data,
	}
	if data {
		result.Original = "@"
	}
	return result
}
func (node *PathExpression) String() string {
	return fmt.Sprintf("Path{Original:'%s', Pos:%d}", node.Original, node.Loc.Pos)
}
func (node *PathExpression) Accept(visitor Visitor) interface{} {
	return visitor.VisitPath(node)
}
func (node *PathExpression) Part(part string) {
	node.Original += part
	switch part {
	case "..":
		node.Depth++
		node.Scoped = true
	case ".", "this":
		node.Scoped = true
	default:
		node.Parts = append(node.Parts, part)
	}
}
func (node *PathExpression) Sep(separator string) {
	node.Original += separator
}
func (node *PathExpression) IsDataRoot() bool {
	return node.Data && (node.Parts[0] == "root")
}
type StringLiteral struct {
	NodeType
	Loc
	Value string
}
func NewStringLiteral(pos int, line int, val string) *StringLiteral {
	return &StringLiteral{
		NodeType: NodeString,
		Loc:      Loc{pos, line},
		Value: val,
	}
}
func (node *StringLiteral) String() string {
	return fmt.Sprintf("String{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
}
func (node *StringLiteral) Accept(visitor Visitor) interface{} {
	return visitor.VisitString(node)
}
type BooleanLiteral struct {
	NodeType
	Loc
	Value    bool
	Original string
}
func NewBooleanLiteral(pos int, line int, val bool, original string) *BooleanLiteral {
	return &BooleanLiteral{
		NodeType: NodeBoolean,
		Loc:      Loc{pos, line},
		Value:    val,
		Original: original,
	}
}
func (node *BooleanLiteral) String() string {
	return fmt.Sprintf("Boolean{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos)
}
func (node *BooleanLiteral) Accept(visitor Visitor) interface{} {
	return visitor.VisitBoolean(node)
}
func (node *BooleanLiteral) Canonical() string {
	if node.Value {
		return "true"
	}
	return "false"
}
type NumberLiteral struct {
	NodeType
	Loc
	Value    float64
	IsInt    bool
	Original string
}
func NewNumberLiteral(pos int, line int, val float64, isInt bool, original string) *NumberLiteral {
	return &NumberLiteral{
		NodeType: NodeNumber,
		Loc:      Loc{pos, line},
		Value:    val,
		IsInt:    isInt,
		Original: original,
	}
}
func (node *NumberLiteral) String() string {
	return fmt.Sprintf("Number{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos)
}
func (node *NumberLiteral) Accept(visitor Visitor) interface{} {
	return visitor.VisitNumber(node)
}
func (node *NumberLiteral) Canonical() string {
	prec := -1
	if node.IsInt {
		prec = 0
	}
	return strconv.FormatFloat(node.Value, 'f', prec, 64)
}
func (node *NumberLiteral) Number() interface{} {
	if node.IsInt {
		return int(node.Value)
	}
	return node.Value
}
type Hash struct {
	NodeType
	Loc
	Pairs []*HashPair
}
func NewHash(pos int, line int) *Hash {
	return &Hash{
		NodeType: NodeHash,
		Loc:      Loc{pos, line},
	}
}
func (node *Hash) String() string {
	result := fmt.Sprintf("Hash{[%d", node.Loc.Pos)
	for i, p := range node.Pairs {
		if i > 0 {
			result += ", "
		}
		result += p.String()
	}
	return result + fmt.Sprintf("], Pos:%d}", node.Loc.Pos)
}
func (node *Hash) Accept(visitor Visitor) interface{} {
	return visitor.VisitHash(node)
}
type HashPair struct {
	NodeType
	Loc
	Key string
	Val Node  
}