Files
kubevpn/vendor/github.com/expr-lang/expr/ast/print.go
2025-04-19 10:06:56 +08:00

254 lines
5.8 KiB
Go

package ast
import (
"encoding/json"
"fmt"
"strings"
"github.com/expr-lang/expr/parser/operator"
"github.com/expr-lang/expr/parser/utils"
)
func (n *NilNode) String() string {
return "nil"
}
func (n *IdentifierNode) String() string {
return n.Value
}
func (n *IntegerNode) String() string {
return fmt.Sprintf("%d", n.Value)
}
func (n *FloatNode) String() string {
return fmt.Sprintf("%v", n.Value)
}
func (n *BoolNode) String() string {
return fmt.Sprintf("%t", n.Value)
}
func (n *StringNode) String() string {
return fmt.Sprintf("%q", n.Value)
}
func (n *ConstantNode) String() string {
if n.Value == nil {
return "nil"
}
b, err := json.Marshal(n.Value)
if err != nil {
panic(err)
}
return string(b)
}
func (n *UnaryNode) String() string {
op := n.Operator
if n.Operator == "not" {
op = fmt.Sprintf("%s ", n.Operator)
}
wrap := false
switch b := n.Node.(type) {
case *BinaryNode:
if operator.Binary[b.Operator].Precedence <
operator.Unary[n.Operator].Precedence {
wrap = true
}
case *ConditionalNode:
wrap = true
}
if wrap {
return fmt.Sprintf("%s(%s)", op, n.Node.String())
}
return fmt.Sprintf("%s%s", op, n.Node.String())
}
func (n *BinaryNode) String() string {
if n.Operator == ".." {
return fmt.Sprintf("%s..%s", n.Left, n.Right)
}
var lhs, rhs string
var lwrap, rwrap bool
if l, ok := n.Left.(*UnaryNode); ok {
if operator.Unary[l.Operator].Precedence <
operator.Binary[n.Operator].Precedence {
lwrap = true
}
}
if lb, ok := n.Left.(*BinaryNode); ok {
if operator.Less(lb.Operator, n.Operator) {
lwrap = true
}
if operator.Binary[lb.Operator].Precedence ==
operator.Binary[n.Operator].Precedence &&
operator.Binary[n.Operator].Associativity == operator.Right {
lwrap = true
}
if lb.Operator == "??" {
lwrap = true
}
if operator.IsBoolean(lb.Operator) && n.Operator != lb.Operator {
lwrap = true
}
}
if rb, ok := n.Right.(*BinaryNode); ok {
if operator.Less(rb.Operator, n.Operator) {
rwrap = true
}
if operator.Binary[rb.Operator].Precedence ==
operator.Binary[n.Operator].Precedence &&
operator.Binary[n.Operator].Associativity == operator.Left {
rwrap = true
}
if operator.IsBoolean(rb.Operator) && n.Operator != rb.Operator {
rwrap = true
}
}
if _, ok := n.Left.(*ConditionalNode); ok {
lwrap = true
}
if _, ok := n.Right.(*ConditionalNode); ok {
rwrap = true
}
if lwrap {
lhs = fmt.Sprintf("(%s)", n.Left.String())
} else {
lhs = n.Left.String()
}
if rwrap {
rhs = fmt.Sprintf("(%s)", n.Right.String())
} else {
rhs = n.Right.String()
}
return fmt.Sprintf("%s %s %s", lhs, n.Operator, rhs)
}
func (n *ChainNode) String() string {
return n.Node.String()
}
func (n *MemberNode) String() string {
node := n.Node.String()
if _, ok := n.Node.(*BinaryNode); ok {
node = fmt.Sprintf("(%s)", node)
}
if n.Optional {
if str, ok := n.Property.(*StringNode); ok && utils.IsValidIdentifier(str.Value) {
return fmt.Sprintf("%s?.%s", node, str.Value)
} else {
return fmt.Sprintf("%s?.[%s]", node, n.Property.String())
}
}
if str, ok := n.Property.(*StringNode); ok && utils.IsValidIdentifier(str.Value) {
if _, ok := n.Node.(*PointerNode); ok {
return fmt.Sprintf(".%s", str.Value)
}
return fmt.Sprintf("%s.%s", node, str.Value)
}
return fmt.Sprintf("%s[%s]", node, n.Property.String())
}
func (n *SliceNode) String() string {
if n.From == nil && n.To == nil {
return fmt.Sprintf("%s[:]", n.Node.String())
}
if n.From == nil {
return fmt.Sprintf("%s[:%s]", n.Node.String(), n.To.String())
}
if n.To == nil {
return fmt.Sprintf("%s[%s:]", n.Node.String(), n.From.String())
}
return fmt.Sprintf("%s[%s:%s]", n.Node.String(), n.From.String(), n.To.String())
}
func (n *CallNode) String() string {
arguments := make([]string, len(n.Arguments))
for i, arg := range n.Arguments {
arguments[i] = arg.String()
}
return fmt.Sprintf("%s(%s)", n.Callee.String(), strings.Join(arguments, ", "))
}
func (n *BuiltinNode) String() string {
arguments := make([]string, len(n.Arguments))
for i, arg := range n.Arguments {
arguments[i] = arg.String()
}
return fmt.Sprintf("%s(%s)", n.Name, strings.Join(arguments, ", "))
}
func (n *PredicateNode) String() string {
return n.Node.String()
}
func (n *PointerNode) String() string {
return fmt.Sprintf("#%s", n.Name)
}
func (n *VariableDeclaratorNode) String() string {
return fmt.Sprintf("let %s = %s; %s", n.Name, n.Value.String(), n.Expr.String())
}
func (n *SequenceNode) String() string {
nodes := make([]string, len(n.Nodes))
for i, node := range n.Nodes {
nodes[i] = node.String()
}
return strings.Join(nodes, "; ")
}
func (n *ConditionalNode) String() string {
var cond, exp1, exp2 string
if _, ok := n.Cond.(*ConditionalNode); ok {
cond = fmt.Sprintf("(%s)", n.Cond.String())
} else {
cond = n.Cond.String()
}
if _, ok := n.Exp1.(*ConditionalNode); ok {
exp1 = fmt.Sprintf("(%s)", n.Exp1.String())
} else {
exp1 = n.Exp1.String()
}
if _, ok := n.Exp2.(*ConditionalNode); ok {
exp2 = fmt.Sprintf("(%s)", n.Exp2.String())
} else {
exp2 = n.Exp2.String()
}
return fmt.Sprintf("%s ? %s : %s", cond, exp1, exp2)
}
func (n *ArrayNode) String() string {
nodes := make([]string, len(n.Nodes))
for i, node := range n.Nodes {
nodes[i] = node.String()
}
return fmt.Sprintf("[%s]", strings.Join(nodes, ", "))
}
func (n *MapNode) String() string {
pairs := make([]string, len(n.Pairs))
for i, pair := range n.Pairs {
pairs[i] = pair.String()
}
return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
}
func (n *PairNode) String() string {
if str, ok := n.Key.(*StringNode); ok {
if utils.IsValidIdentifier(str.Value) {
return fmt.Sprintf("%s: %s", str.Value, n.Value.String())
}
return fmt.Sprintf("%s: %s", str.String(), n.Value.String())
}
return fmt.Sprintf("(%s): %s", n.Key.String(), n.Value.String())
}