You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.4 KiB
Go

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) 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) 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) 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) 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 + "}"
}