Files
azalea/schema/ast/ast.go
2026-01-27 21:57:38 -06:00

118 lines
2.1 KiB
Go

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 "<nil>"
}