146 lines
2.8 KiB
Go
146 lines
2.8 KiB
Go
package ast
|
|
|
|
import (
|
|
"azalea/schema/token"
|
|
"azalea/schema/util"
|
|
"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
|
|
rune *rune
|
|
int *int64
|
|
float *float64
|
|
imaginary *complex128
|
|
name *string
|
|
*Expr
|
|
}
|
|
|
|
func NewStringVal(val *token.Token) (Val, error) {
|
|
s, err := strconv.Unquote(string(val.Lit))
|
|
return Val{string: &s}, err
|
|
}
|
|
func NewRuneVal(val *token.Token) (Val, error) {
|
|
r := util.RuneValue(val.Lit)
|
|
return Val{rune: &r}, nil
|
|
}
|
|
func NewIntVal(val *token.Token) (Val, error) {
|
|
i, err := strconv.ParseInt(string(val.Lit), 0, 64)
|
|
return Val{int: &i}, err
|
|
}
|
|
|
|
func NewFloatVal(val *token.Token) (Val, error) {
|
|
f, err := strconv.ParseFloat(string(val.Lit), 64)
|
|
return Val{float: &f}, err
|
|
}
|
|
|
|
func NewComplexVal(val *token.Token) (Val, error) {
|
|
c, err := strconv.ParseComplex(string(val.Lit), 128)
|
|
return Val{imaginary: &c}, err
|
|
}
|
|
|
|
func NewNameVal(val *token.Token) (Val, error) {
|
|
name := string(val.Lit)
|
|
return Val{name: &name}, nil
|
|
}
|
|
|
|
func NewExprVal(val any) (Val, error) {
|
|
expr := val.(Expr)
|
|
return Val{Expr: &expr}, nil
|
|
}
|
|
|
|
func NewExprList(expr any) (ExprList, error) {
|
|
return ExprList{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 != nil {
|
|
return *v.string
|
|
}
|
|
if v.rune != nil {
|
|
return string(*v.rune)
|
|
}
|
|
if v.int != nil {
|
|
return strconv.FormatInt(*v.int, 10)
|
|
}
|
|
if v.float != nil {
|
|
return strconv.FormatFloat(*v.float, 'g', -1, 64)
|
|
}
|
|
if v.imaginary != nil {
|
|
return strconv.FormatComplex(*v.imaginary, 'g', -1, 128)
|
|
}
|
|
if v.name != nil {
|
|
return *v.name
|
|
}
|
|
if v.Expr != nil {
|
|
return v.Expr.String()
|
|
}
|
|
return "<nil>"
|
|
}
|