package ast import ( "azalea/schema/token" "strconv" "strings" ) type Schema ExprList type ExprList []Expr type Expr struct { Name string Left *Val Right *Val } type ValList []Val type Val struct { string string number string name string *Expr } func NewExprList(expr any) (ExprList, error) { return ExprList{expr.(Expr)}, nil } func NewStringVal(val *token.Token) (Val, error) { return Val{string: string(val.Lit)}, nil } func NewNumberVal(val *token.Token) (Val, error) { return Val{number: string(val.Lit)}, nil } func NewNameVal(val *token.Token) (Val, error) { return Val{name: string(val.Lit)}, nil } func NewExprVal(val any) (Val, error) { expr := val.(Expr) return Val{Expr: &expr}, nil } func AppendExpr(exprList, expr any) (ExprList, error) { return append(exprList.(ExprList), expr.(Expr)), nil } func NewValList(val any) (ValList, error) { return ValList{val.(Val)}, nil } func AppendVal(valList, val any) (ValList, error) { return append(valList.(ValList), val.(Val)), nil } func NewExpr(name *token.Token, left any, right any) (Expr, error) { var l Val var r Val if left != nil { l = left.(Val) } if right != nil { r = right.(Val) } return Expr{string(name.Lit), &l, &r}, nil } func ListExpr(val any) (Expr, error) { vals := val.(ValList) root := Expr{ Name: ".", } current := &root for _, val := range vals[:len(vals)-2] { current.Left = &val current.Right = &Val{ Expr: &Expr{ Name: ".", }} current = current.Right.Expr } current.Left = &vals[len(vals)-2] current.Right = &vals[len(vals)-1] return root, nil } func (e Expr) String() string { sb := new(strings.Builder) sb.WriteRune('(') sb.WriteString(e.Name) sb.WriteRune(' ') if e.Left != nil { sb.WriteString(e.Left.String()) } sb.WriteRune(' ') if e.Left != nil { sb.WriteString(e.Right.String()) } sb.WriteRune(')') return sb.String() } func (v *Val) String() string { if v.string != "" { return v.string } if v.number != "" { num, _ := strconv.ParseInt(v.number, 0, 64) return strconv.FormatInt(num, 10) } if v.name != "" { return v.name } if v.Expr != nil { return v.Expr.String() } return "" }