switch glide to govendor (#43)
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
785
vendor/github.com/aymerick/raymond/ast/node.go
generated
vendored
Normal file
785
vendor/github.com/aymerick/raymond/ast/node.go
generated
vendored
Normal file
@ -0,0 +1,785 @@
|
||||
// Package ast provides structures to represent a handlebars Abstract Syntax Tree, and a Visitor interface to visit that tree.
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// References:
|
||||
// - https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler/ast.js
|
||||
// - https://github.com/wycats/handlebars.js/blob/master/docs/compiler-api.md
|
||||
// - https://github.com/golang/go/blob/master/src/text/template/parse/node.go
|
||||
|
||||
// Node is an element in the AST.
|
||||
type Node interface {
|
||||
// node type
|
||||
Type() NodeType
|
||||
|
||||
// location of node in original input string
|
||||
Location() Loc
|
||||
|
||||
// string representation, used for debugging
|
||||
String() string
|
||||
|
||||
// accepts visitor
|
||||
Accept(Visitor) interface{}
|
||||
}
|
||||
|
||||
// Visitor is the interface to visit an AST.
|
||||
type Visitor interface {
|
||||
VisitProgram(*Program) interface{}
|
||||
|
||||
// statements
|
||||
VisitMustache(*MustacheStatement) interface{}
|
||||
VisitBlock(*BlockStatement) interface{}
|
||||
VisitPartial(*PartialStatement) interface{}
|
||||
VisitContent(*ContentStatement) interface{}
|
||||
VisitComment(*CommentStatement) interface{}
|
||||
|
||||
// expressions
|
||||
VisitExpression(*Expression) interface{}
|
||||
VisitSubExpression(*SubExpression) interface{}
|
||||
VisitPath(*PathExpression) interface{}
|
||||
|
||||
// literals
|
||||
VisitString(*StringLiteral) interface{}
|
||||
VisitBoolean(*BooleanLiteral) interface{}
|
||||
VisitNumber(*NumberLiteral) interface{}
|
||||
|
||||
// miscellaneous
|
||||
VisitHash(*Hash) interface{}
|
||||
VisitHashPair(*HashPair) interface{}
|
||||
}
|
||||
|
||||
// NodeType represents an AST Node type.
|
||||
type NodeType int
|
||||
|
||||
// Type returns itself, and permits struct includers to satisfy that part of Node interface.
|
||||
func (t NodeType) Type() NodeType {
|
||||
return t
|
||||
}
|
||||
|
||||
const (
|
||||
// NodeProgram is the program node
|
||||
NodeProgram NodeType = iota
|
||||
|
||||
// NodeMustache is the mustache statement node
|
||||
NodeMustache
|
||||
|
||||
// NodeBlock is the block statement node
|
||||
NodeBlock
|
||||
|
||||
// NodePartial is the partial statement node
|
||||
NodePartial
|
||||
|
||||
// NodeContent is the content statement node
|
||||
NodeContent
|
||||
|
||||
// NodeComment is the comment statement node
|
||||
NodeComment
|
||||
|
||||
// NodeExpression is the expression node
|
||||
NodeExpression
|
||||
|
||||
// NodeSubExpression is the subexpression node
|
||||
NodeSubExpression
|
||||
|
||||
// NodePath is the expression path node
|
||||
NodePath
|
||||
|
||||
// NodeBoolean is the literal boolean node
|
||||
NodeBoolean
|
||||
|
||||
// NodeNumber is the literal number node
|
||||
NodeNumber
|
||||
|
||||
// NodeString is the literal string node
|
||||
NodeString
|
||||
|
||||
// NodeHash is the hash node
|
||||
NodeHash
|
||||
|
||||
// NodeHashPair is the hash pair node
|
||||
NodeHashPair
|
||||
)
|
||||
|
||||
// Loc represents the position of a parsed node in source file.
|
||||
type Loc struct {
|
||||
Pos int // Byte position
|
||||
Line int // Line number
|
||||
}
|
||||
|
||||
// Location returns itself, and permits struct includers to satisfy that part of Node interface.
|
||||
func (l Loc) Location() Loc {
|
||||
return l
|
||||
}
|
||||
|
||||
// Strip describes node whitespace management.
|
||||
type Strip struct {
|
||||
Open bool
|
||||
Close bool
|
||||
|
||||
OpenStandalone bool
|
||||
CloseStandalone bool
|
||||
InlineStandalone bool
|
||||
}
|
||||
|
||||
// NewStrip instanciates a Strip for given open and close mustaches.
|
||||
func NewStrip(openStr, closeStr string) *Strip {
|
||||
return &Strip{
|
||||
Open: (len(openStr) > 2) && openStr[2] == '~',
|
||||
Close: (len(closeStr) > 2) && closeStr[len(closeStr)-3] == '~',
|
||||
}
|
||||
}
|
||||
|
||||
// NewStripForStr instanciates a Strip for given tag.
|
||||
func NewStripForStr(str string) *Strip {
|
||||
return &Strip{
|
||||
Open: (len(str) > 2) && str[2] == '~',
|
||||
Close: (len(str) > 2) && str[len(str)-3] == '~',
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
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)
|
||||
}
|
||||
|
||||
//
|
||||
// Program
|
||||
//
|
||||
|
||||
// Program represents a program node.
|
||||
type Program struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Body []Node // [ Statement ... ]
|
||||
BlockParams []string
|
||||
Chained bool
|
||||
|
||||
// whitespace management
|
||||
Strip *Strip
|
||||
}
|
||||
|
||||
// NewProgram instanciates a new program node.
|
||||
func NewProgram(pos int, line int) *Program {
|
||||
return &Program{
|
||||
NodeType: NodeProgram,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *Program) String() string {
|
||||
return fmt.Sprintf("Program{Pos: %d}", node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *Program) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitProgram(node)
|
||||
}
|
||||
|
||||
// AddStatement adds given statement to program.
|
||||
func (node *Program) AddStatement(statement Node) {
|
||||
node.Body = append(node.Body, statement)
|
||||
}
|
||||
|
||||
//
|
||||
// Mustache Statement
|
||||
//
|
||||
|
||||
// MustacheStatement represents a mustache node.
|
||||
type MustacheStatement struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Unescaped bool
|
||||
Expression *Expression
|
||||
|
||||
// whitespace management
|
||||
Strip *Strip
|
||||
}
|
||||
|
||||
// NewMustacheStatement instanciates a new mustache node.
|
||||
func NewMustacheStatement(pos int, line int, unescaped bool) *MustacheStatement {
|
||||
return &MustacheStatement{
|
||||
NodeType: NodeMustache,
|
||||
Loc: Loc{pos, line},
|
||||
Unescaped: unescaped,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *MustacheStatement) String() string {
|
||||
return fmt.Sprintf("Mustache{Pos: %d}", node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *MustacheStatement) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitMustache(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Block Statement
|
||||
//
|
||||
|
||||
// BlockStatement represents a block node.
|
||||
type BlockStatement struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Expression *Expression
|
||||
|
||||
Program *Program
|
||||
Inverse *Program
|
||||
|
||||
// whitespace management
|
||||
OpenStrip *Strip
|
||||
InverseStrip *Strip
|
||||
CloseStrip *Strip
|
||||
}
|
||||
|
||||
// NewBlockStatement instanciates a new block node.
|
||||
func NewBlockStatement(pos int, line int) *BlockStatement {
|
||||
return &BlockStatement{
|
||||
NodeType: NodeBlock,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *BlockStatement) String() string {
|
||||
return fmt.Sprintf("Block{Pos: %d}", node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *BlockStatement) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitBlock(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Partial Statement
|
||||
//
|
||||
|
||||
// PartialStatement represents a partial node.
|
||||
type PartialStatement struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Name Node // PathExpression | SubExpression
|
||||
Params []Node // [ Expression ... ]
|
||||
Hash *Hash
|
||||
|
||||
// whitespace management
|
||||
Strip *Strip
|
||||
Indent string
|
||||
}
|
||||
|
||||
// NewPartialStatement instanciates a new partial node.
|
||||
func NewPartialStatement(pos int, line int) *PartialStatement {
|
||||
return &PartialStatement{
|
||||
NodeType: NodePartial,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *PartialStatement) String() string {
|
||||
return fmt.Sprintf("Partial{Name:%s, Pos:%d}", node.Name, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *PartialStatement) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitPartial(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Content Statement
|
||||
//
|
||||
|
||||
// ContentStatement represents a content node.
|
||||
type ContentStatement struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Value string
|
||||
Original string
|
||||
|
||||
// whitespace management
|
||||
RightStripped bool
|
||||
LeftStripped bool
|
||||
}
|
||||
|
||||
// NewContentStatement instanciates a new content node.
|
||||
func NewContentStatement(pos int, line int, val string) *ContentStatement {
|
||||
return &ContentStatement{
|
||||
NodeType: NodeContent,
|
||||
Loc: Loc{pos, line},
|
||||
|
||||
Value: val,
|
||||
Original: val,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *ContentStatement) String() string {
|
||||
return fmt.Sprintf("Content{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *ContentStatement) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitContent(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Comment Statement
|
||||
//
|
||||
|
||||
// CommentStatement represents a comment node.
|
||||
type CommentStatement struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Value string
|
||||
|
||||
// whitespace management
|
||||
Strip *Strip
|
||||
}
|
||||
|
||||
// NewCommentStatement instanciates a new comment node.
|
||||
func NewCommentStatement(pos int, line int, val string) *CommentStatement {
|
||||
return &CommentStatement{
|
||||
NodeType: NodeComment,
|
||||
Loc: Loc{pos, line},
|
||||
|
||||
Value: val,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *CommentStatement) String() string {
|
||||
return fmt.Sprintf("Comment{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *CommentStatement) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitComment(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Expression
|
||||
//
|
||||
|
||||
// Expression represents an expression node.
|
||||
type Expression struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Path Node // PathExpression | StringLiteral | BooleanLiteral | NumberLiteral
|
||||
Params []Node // [ Expression ... ]
|
||||
Hash *Hash
|
||||
}
|
||||
|
||||
// NewExpression instanciates a new expression node.
|
||||
func NewExpression(pos int, line int) *Expression {
|
||||
return &Expression{
|
||||
NodeType: NodeExpression,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *Expression) String() string {
|
||||
return fmt.Sprintf("Expr{Path:%s, Pos:%d}", node.Path, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *Expression) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitExpression(node)
|
||||
}
|
||||
|
||||
// HelperName returns helper name, or an empty string if this expression can't be a helper.
|
||||
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]
|
||||
}
|
||||
|
||||
// FieldPath returns path expression representing a field path, or nil if this is not a field path.
|
||||
func (node *Expression) FieldPath() *PathExpression {
|
||||
path, ok := node.Path.(*PathExpression)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// LiteralStr returns the string representation of literal value, with a boolean set to false if this is not a literal.
|
||||
func (node *Expression) LiteralStr() (string, bool) {
|
||||
return LiteralStr(node.Path)
|
||||
}
|
||||
|
||||
// Canonical returns the canonical form of expression node as a string.
|
||||
func (node *Expression) Canonical() string {
|
||||
if str, ok := HelperNameStr(node.Path); ok {
|
||||
return str
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// HelperNameStr returns the string representation of a helper name, with a boolean set to false if this is not a valid helper name.
|
||||
//
|
||||
// helperName : path | dataName | STRING | NUMBER | BOOLEAN | UNDEFINED | NULL
|
||||
func HelperNameStr(node Node) (string, bool) {
|
||||
// PathExpression
|
||||
if str, ok := PathExpressionStr(node); ok {
|
||||
return str, ok
|
||||
}
|
||||
|
||||
// Literal
|
||||
if str, ok := LiteralStr(node); ok {
|
||||
return str, ok
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
// PathExpressionStr returns the string representation of path expression value, with a boolean set to false if this is not a path expression.
|
||||
func PathExpressionStr(node Node) (string, bool) {
|
||||
if path, ok := node.(*PathExpression); ok {
|
||||
result := path.Original
|
||||
|
||||
// "[foo bar]"" => "foo bar"
|
||||
if (len(result) >= 2) && (result[0] == '[') && (result[len(result)-1] == ']') {
|
||||
result = result[1 : len(result)-1]
|
||||
}
|
||||
|
||||
return result, true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
|
||||
// LiteralStr returns the string representation of literal value, with a boolean set to false if this is not a literal.
|
||||
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
|
||||
}
|
||||
|
||||
//
|
||||
// SubExpression
|
||||
//
|
||||
|
||||
// SubExpression represents a subexpression node.
|
||||
type SubExpression struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Expression *Expression
|
||||
}
|
||||
|
||||
// NewSubExpression instanciates a new subexpression node.
|
||||
func NewSubExpression(pos int, line int) *SubExpression {
|
||||
return &SubExpression{
|
||||
NodeType: NodeSubExpression,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *SubExpression) String() string {
|
||||
return fmt.Sprintf("Sexp{Path:%s, Pos:%d}", node.Expression.Path, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *SubExpression) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitSubExpression(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Path Expression
|
||||
//
|
||||
|
||||
// PathExpression represents a path expression node.
|
||||
type PathExpression struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Original string
|
||||
Depth int
|
||||
Parts []string
|
||||
Data bool
|
||||
Scoped bool
|
||||
}
|
||||
|
||||
// NewPathExpression instanciates a new path expression node.
|
||||
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
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *PathExpression) String() string {
|
||||
return fmt.Sprintf("Path{Original:'%s', Pos:%d}", node.Original, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *PathExpression) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitPath(node)
|
||||
}
|
||||
|
||||
// Part adds path part.
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Sep adds path separator.
|
||||
func (node *PathExpression) Sep(separator string) {
|
||||
node.Original += separator
|
||||
}
|
||||
|
||||
// IsDataRoot returns true if path expression is @root.
|
||||
func (node *PathExpression) IsDataRoot() bool {
|
||||
return node.Data && (node.Parts[0] == "root")
|
||||
}
|
||||
|
||||
//
|
||||
// String Literal
|
||||
//
|
||||
|
||||
// StringLiteral represents a string node.
|
||||
type StringLiteral struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Value string
|
||||
}
|
||||
|
||||
// NewStringLiteral instanciates a new string node.
|
||||
func NewStringLiteral(pos int, line int, val string) *StringLiteral {
|
||||
return &StringLiteral{
|
||||
NodeType: NodeString,
|
||||
Loc: Loc{pos, line},
|
||||
|
||||
Value: val,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *StringLiteral) String() string {
|
||||
return fmt.Sprintf("String{Value:'%s', Pos:%d}", node.Value, node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *StringLiteral) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitString(node)
|
||||
}
|
||||
|
||||
//
|
||||
// Boolean Literal
|
||||
//
|
||||
|
||||
// BooleanLiteral represents a boolean node.
|
||||
type BooleanLiteral struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Value bool
|
||||
Original string
|
||||
}
|
||||
|
||||
// NewBooleanLiteral instanciates a new boolean node.
|
||||
func NewBooleanLiteral(pos int, line int, val bool, original string) *BooleanLiteral {
|
||||
return &BooleanLiteral{
|
||||
NodeType: NodeBoolean,
|
||||
Loc: Loc{pos, line},
|
||||
|
||||
Value: val,
|
||||
Original: original,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *BooleanLiteral) String() string {
|
||||
return fmt.Sprintf("Boolean{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *BooleanLiteral) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitBoolean(node)
|
||||
}
|
||||
|
||||
// Canonical returns the canonical form of boolean node as a string (ie. "true" | "false").
|
||||
func (node *BooleanLiteral) Canonical() string {
|
||||
if node.Value {
|
||||
return "true"
|
||||
}
|
||||
|
||||
return "false"
|
||||
}
|
||||
|
||||
//
|
||||
// Number Literal
|
||||
//
|
||||
|
||||
// NumberLiteral represents a number node.
|
||||
type NumberLiteral struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Value float64
|
||||
IsInt bool
|
||||
Original string
|
||||
}
|
||||
|
||||
// NewNumberLiteral instanciates a new number node.
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *NumberLiteral) String() string {
|
||||
return fmt.Sprintf("Number{Value:%s, Pos:%d}", node.Canonical(), node.Loc.Pos)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *NumberLiteral) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitNumber(node)
|
||||
}
|
||||
|
||||
// Canonical returns the canonical form of number node as a string (eg: "12", "-1.51").
|
||||
func (node *NumberLiteral) Canonical() string {
|
||||
prec := -1
|
||||
if node.IsInt {
|
||||
prec = 0
|
||||
}
|
||||
return strconv.FormatFloat(node.Value, 'f', prec, 64)
|
||||
}
|
||||
|
||||
// Number returns an integer or a float.
|
||||
func (node *NumberLiteral) Number() interface{} {
|
||||
if node.IsInt {
|
||||
return int(node.Value)
|
||||
}
|
||||
|
||||
return node.Value
|
||||
}
|
||||
|
||||
//
|
||||
// Hash
|
||||
//
|
||||
|
||||
// Hash represents a hash node.
|
||||
type Hash struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Pairs []*HashPair
|
||||
}
|
||||
|
||||
// NewHash instanciates a new hash node.
|
||||
func NewHash(pos int, line int) *Hash {
|
||||
return &Hash{
|
||||
NodeType: NodeHash,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
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)
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *Hash) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitHash(node)
|
||||
}
|
||||
|
||||
//
|
||||
// HashPair
|
||||
//
|
||||
|
||||
// HashPair represents a hash pair node.
|
||||
type HashPair struct {
|
||||
NodeType
|
||||
Loc
|
||||
|
||||
Key string
|
||||
Val Node // Expression
|
||||
}
|
||||
|
||||
// NewHashPair instanciates a new hash pair node.
|
||||
func NewHashPair(pos int, line int) *HashPair {
|
||||
return &HashPair{
|
||||
NodeType: NodeHashPair,
|
||||
Loc: Loc{pos, line},
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of receiver that can be used for debugging.
|
||||
func (node *HashPair) String() string {
|
||||
return node.Key + "=" + node.Val.String()
|
||||
}
|
||||
|
||||
// Accept is the receiver entry point for visitors.
|
||||
func (node *HashPair) Accept(visitor Visitor) interface{} {
|
||||
return visitor.VisitHashPair(node)
|
||||
}
|
279
vendor/github.com/aymerick/raymond/ast/print.go
generated
vendored
Normal file
279
vendor/github.com/aymerick/raymond/ast/print.go
generated
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// printVisitor implements the Visitor interface to print a AST.
|
||||
type printVisitor struct {
|
||||
buf string
|
||||
depth int
|
||||
|
||||
original bool
|
||||
inBlock bool
|
||||
}
|
||||
|
||||
func newPrintVisitor() *printVisitor {
|
||||
return &printVisitor{}
|
||||
}
|
||||
|
||||
// Print returns a string representation of given AST, that can be used for debugging purpose.
|
||||
func Print(node Node) string {
|
||||
visitor := newPrintVisitor()
|
||||
node.Accept(visitor)
|
||||
return visitor.output()
|
||||
}
|
||||
|
||||
func (v *printVisitor) output() string {
|
||||
return v.buf
|
||||
}
|
||||
|
||||
func (v *printVisitor) indent() {
|
||||
for i := 0; i < v.depth; {
|
||||
v.buf += " "
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func (v *printVisitor) str(val string) {
|
||||
v.buf += val
|
||||
}
|
||||
|
||||
func (v *printVisitor) nl() {
|
||||
v.str("\n")
|
||||
}
|
||||
|
||||
func (v *printVisitor) line(val string) {
|
||||
v.indent()
|
||||
v.str(val)
|
||||
v.nl()
|
||||
}
|
||||
|
||||
//
|
||||
// Visitor interface
|
||||
//
|
||||
|
||||
// Statements
|
||||
|
||||
// VisitProgram implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitProgram(node *Program) interface{} {
|
||||
if len(node.BlockParams) > 0 {
|
||||
v.line("BLOCK PARAMS: [ " + strings.Join(node.BlockParams, " ") + " ]")
|
||||
}
|
||||
|
||||
for _, n := range node.Body {
|
||||
n.Accept(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitMustache implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitMustache(node *MustacheStatement) interface{} {
|
||||
v.indent()
|
||||
v.str("{{ ")
|
||||
|
||||
node.Expression.Accept(v)
|
||||
|
||||
v.str(" }}")
|
||||
v.nl()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitBlock implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitBlock(node *BlockStatement) interface{} {
|
||||
v.inBlock = true
|
||||
|
||||
v.line("BLOCK:")
|
||||
v.depth++
|
||||
|
||||
node.Expression.Accept(v)
|
||||
|
||||
if node.Program != nil {
|
||||
v.line("PROGRAM:")
|
||||
v.depth++
|
||||
node.Program.Accept(v)
|
||||
v.depth--
|
||||
}
|
||||
|
||||
if node.Inverse != nil {
|
||||
// if node.Program != nil {
|
||||
// v.depth++
|
||||
// }
|
||||
|
||||
v.line("{{^}}")
|
||||
v.depth++
|
||||
node.Inverse.Accept(v)
|
||||
v.depth--
|
||||
|
||||
// if node.Program != nil {
|
||||
// v.depth--
|
||||
// }
|
||||
}
|
||||
|
||||
v.inBlock = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitPartial implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitPartial(node *PartialStatement) interface{} {
|
||||
v.indent()
|
||||
v.str("{{> PARTIAL:")
|
||||
|
||||
v.original = true
|
||||
node.Name.Accept(v)
|
||||
v.original = false
|
||||
|
||||
if len(node.Params) > 0 {
|
||||
v.str(" ")
|
||||
node.Params[0].Accept(v)
|
||||
}
|
||||
|
||||
// hash
|
||||
if node.Hash != nil {
|
||||
v.str(" ")
|
||||
node.Hash.Accept(v)
|
||||
}
|
||||
|
||||
v.str(" }}")
|
||||
v.nl()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitContent implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitContent(node *ContentStatement) interface{} {
|
||||
v.line("CONTENT[ '" + node.Value + "' ]")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitComment implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitComment(node *CommentStatement) interface{} {
|
||||
v.line("{{! '" + node.Value + "' }}")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Expressions
|
||||
|
||||
// VisitExpression implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitExpression(node *Expression) interface{} {
|
||||
if v.inBlock {
|
||||
v.indent()
|
||||
}
|
||||
|
||||
// path
|
||||
node.Path.Accept(v)
|
||||
|
||||
// params
|
||||
v.str(" [")
|
||||
for i, n := range node.Params {
|
||||
if i > 0 {
|
||||
v.str(", ")
|
||||
}
|
||||
n.Accept(v)
|
||||
}
|
||||
v.str("]")
|
||||
|
||||
// hash
|
||||
if node.Hash != nil {
|
||||
v.str(" ")
|
||||
node.Hash.Accept(v)
|
||||
}
|
||||
|
||||
if v.inBlock {
|
||||
v.nl()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitSubExpression implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitSubExpression(node *SubExpression) interface{} {
|
||||
node.Expression.Accept(v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitPath implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitPath(node *PathExpression) interface{} {
|
||||
if v.original {
|
||||
v.str(node.Original)
|
||||
} else {
|
||||
path := strings.Join(node.Parts, "/")
|
||||
|
||||
result := ""
|
||||
if node.Data {
|
||||
result += "@"
|
||||
}
|
||||
|
||||
v.str(result + "PATH:" + path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Literals
|
||||
|
||||
// VisitString implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitString(node *StringLiteral) interface{} {
|
||||
if v.original {
|
||||
v.str(node.Value)
|
||||
} else {
|
||||
v.str("\"" + node.Value + "\"")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitBoolean implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitBoolean(node *BooleanLiteral) interface{} {
|
||||
if v.original {
|
||||
v.str(node.Original)
|
||||
} else {
|
||||
v.str(fmt.Sprintf("BOOLEAN{%s}", node.Canonical()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitNumber implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitNumber(node *NumberLiteral) interface{} {
|
||||
if v.original {
|
||||
v.str(node.Original)
|
||||
} else {
|
||||
v.str(fmt.Sprintf("NUMBER{%s}", node.Canonical()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
// VisitHash implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitHash(node *Hash) interface{} {
|
||||
v.str("HASH{")
|
||||
|
||||
for i, p := range node.Pairs {
|
||||
if i > 0 {
|
||||
v.str(", ")
|
||||
}
|
||||
p.Accept(v)
|
||||
}
|
||||
|
||||
v.str("}")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VisitHashPair implements corresponding Visitor interface method
|
||||
func (v *printVisitor) VisitHashPair(node *HashPair) interface{} {
|
||||
v.str(node.Key + "=")
|
||||
node.Val.Accept(v)
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user