package ast import ( "fmt" ) type Printer struct { } func NewPrinter() *Printer { return &Printer{} } func (ap *Printer) PrintStmts(stmts []Stmt) string { str := "" for _, stmt := range stmts { str += stmt.Accept(ap).(string) + "\n" } return str } func (ap *Printer) PrintExpr(expr Expr) string { return expr.Accept(ap).(string) } func (ap *Printer) VisitErrorStmt(stmt *ErrorStmt) any { return stmt.Value } func (ap *Printer) VisitExpressionStmt(stmt *ExpressionStmt) any { return stmt.Expression.Accept(ap) } func (ap *Printer) VisitFunctionStmt(stmt *FunctionStmt) any { str := "(fun " + stmt.Name.Lexeme + "(" for i, param := range stmt.Params { if i > 0 { str += ", " } str += param.Lexeme } str += ")" if stmt.Body != nil { str += " " + ap.bracesizeStmt(stmt.Body...) } return str + ")" } func (ap *Printer) VisitPrintStmt(stmt *PrintStmt) any { return ap.parenthesizeExpr("print", stmt.Expression) } func (ap *Printer) VisitIfStmt(stmt *IfStmt) any { str := "(if" if stmt.Condition != nil { str += " " + stmt.Condition.Accept(ap).(string) } if stmt.ThenBranch != nil { str += " " + ap.bracesizeStmt(stmt.ThenBranch) } if stmt.ElseBranch != nil { str += " else " + ap.bracesizeStmt(stmt.ElseBranch) } return str + ")" } func (ap *Printer) VisitVarStmt(stmt *VarStmt) any { return ap.parenthesizeExpr("var", &LiteralExpr{stmt.Name}, stmt.Initializer) } func (ap *Printer) VisitWhileStmt(stmt *WhileStmt) any { str := "(while" if stmt.Condition != nil { str += " " + stmt.Condition.Accept(ap).(string) } if stmt.Body != nil { str += " " + ap.bracesizeStmt(stmt.Body) } return str + ")" } func (ap *Printer) VisitBlockStmt(stmt *BlockStmt) any { return ap.bracesizeStmt(stmt.Statements...) } func (ap *Printer) VisitVariableExpr(expr *VariableExpr) any { return expr.Name.Lexeme } func (ap *Printer) VisitBinaryExpr(expr *BinaryExpr) any { return ap.parenthesizeExpr(expr.Operator.Lexeme, expr.Left, expr.Right) } func (ap *Printer) VisitCallExpr(expr *CallExpr) any { str := expr.Callee.Accept(ap).(string) + "(" for i, arg := range expr.Arguments { if i > 0 { str += ", " } str += arg.Accept(ap).(string) } return str + ")" } func (ap *Printer) VisitGroupingExpr(expr *GroupingExpr) any { return ap.parenthesizeExpr("group", expr.Expression) } func (ap *Printer) VisitLiteralExpr(expr *LiteralExpr) any { if expr.Value == nil { return "nil" } return fmt.Sprint(expr.Value) } func (ap *Printer) VisitLogicalExpr(expr *LogicalExpr) any { return ap.parenthesizeExpr(expr.Operator.Lexeme, expr.Left, expr.Right) } func (ap *Printer) VisitUnaryExpr(expr *UnaryExpr) any { return ap.parenthesizeExpr(expr.Operator.Lexeme, expr.Right) } func (ap *Printer) VisitErrorExpr(expr *ErrorExpr) any { return expr.Value } func (ap *Printer) VisitAssignExpr(expr *AssignExpr) any { return ap.parenthesizeExpr("=", &VariableExpr{expr.Name}, expr.Value) } func (ap *Printer) parenthesizeExpr(name string, exprs ...Expr) string { str := "(" + name for _, expr := range exprs { if expr == nil { continue } str += " " + expr.Accept(ap).(string) } return str + ")" } func (ap *Printer) bracesizeStmt(stmts ...Stmt) string { str := "{\n" for _, s := range stmts { str += " " + s.Accept(ap).(string) + "\n" } return str + "}" }