package ast import ( "fmt" "strconv" ) type Printer struct { result string } var _ ExprVisitor = new(Printer) func (p *Printer) VisitBinaryExpr(b *BinaryExpr) any { return p.Parenthesize(b.Operator.Lexeme, b.Left, b.Right) } func (p *Printer) VisitGroupingExpr(g *GroupingExpr) any { return p.Parenthesize("group", g.Expr) } func (p *Printer) VisitLiteralExpr(g *LiteralExpr) any { switch t := g.Value.(type) { case string: return t case bool: if t { return "true" } return "false" case float64: return strconv.FormatFloat(t, 'f', 3, 64) case nil: return "nil" } return fmt.Sprintf("%v", g.Value) } func (p *Printer) VisitUnaryExpr(g *UnaryExpr) any { return p.Parenthesize(g.Operator.Lexeme, g.Right) } func (p *Printer) Parenthesize(name string, expressions ...Expr) string { val := "(" + name for _, e := range expressions { exprStr, ok := (e.accept(p)).(string) if !ok { panic("badly implemented visitor") } val += " " + exprStr } val += ")" return val } func (p *Printer) Print(e Expr) string { str, ok := (e.accept(p)).(string) if !ok { panic("badly implemented visitor") } return str }