2024-10-04 15:24:01 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AstStringer struct {
|
2024-10-05 23:27:00 +03:00
|
|
|
str strings.Builder
|
|
|
|
stmts []Stmt
|
2024-10-04 15:24:01 +03:00
|
|
|
}
|
|
|
|
|
2024-10-05 23:27:00 +03:00
|
|
|
func (as AstStringer) String() string {
|
2024-10-04 15:24:01 +03:00
|
|
|
|
2024-10-05 23:27:00 +03:00
|
|
|
for _, stmt := range as.stmts {
|
2024-10-05 18:58:49 +03:00
|
|
|
stmt.accept(&as)
|
2024-10-04 15:24:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return as.str.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitBinary(b *Binary) any {
|
|
|
|
as.str.WriteString("(")
|
|
|
|
as.str.WriteString(b.op.lexeme)
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
b.left.accept(as)
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
b.right.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitLiteral(l *Literal) any {
|
|
|
|
as.str.WriteString(fmt.Sprintf("%v", l.value))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitGrouping(g *Grouping) any {
|
|
|
|
as.str.WriteString("(group ")
|
|
|
|
g.expression.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitUnary(u *Unary) any {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(%s ", u.op.lexeme))
|
|
|
|
u.right.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
return nil
|
|
|
|
}
|
2024-10-05 18:58:49 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitVariable(va *Variable) any {
|
|
|
|
as.str.WriteString(va.name.lexeme)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitAssignment(a *Assign) any {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(= %s ", a.variable.lexeme))
|
|
|
|
a.value.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-10-06 17:15:50 +03:00
|
|
|
func (as *AstStringer) visitLogical(l *Logical) any {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(%s ", l.operator.lexeme))
|
2024-10-06 16:30:57 +03:00
|
|
|
l.left.accept(as)
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
l.right.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-10-09 19:57:52 +03:00
|
|
|
func (as *AstStringer) visitCall(c *Call) any {
|
|
|
|
as.str.WriteString("(call ")
|
|
|
|
c.callee.accept(as)
|
2024-10-11 17:01:12 +03:00
|
|
|
as.str.WriteString(" ")
|
|
|
|
for i, arg := range c.args {
|
2024-10-09 19:57:52 +03:00
|
|
|
arg.accept(as)
|
2024-10-11 17:01:12 +03:00
|
|
|
if i < len(c.args)-1 {
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
}
|
2024-10-09 19:57:52 +03:00
|
|
|
}
|
|
|
|
as.str.WriteString(")")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-10-05 18:58:49 +03:00
|
|
|
func (as *AstStringer) visitPrintStmt(p *PrintStmt) {
|
|
|
|
as.str.WriteString("(print ")
|
|
|
|
p.val.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitExprStmt(se *ExprStmt) {
|
|
|
|
se.expr.accept(as)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitVarStmt(vs *VarStmt) {
|
|
|
|
if vs.initializer != nil {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(var %v ", vs.name.literal))
|
|
|
|
vs.initializer.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
} else {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(var %v)", vs.name.literal))
|
|
|
|
}
|
|
|
|
}
|
2024-10-05 23:27:00 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitBlockStmt(b *BlockStmt) {
|
|
|
|
as.str.WriteString("(block ")
|
|
|
|
|
|
|
|
for _, stmt := range b.stmts {
|
|
|
|
stmt.accept(as)
|
|
|
|
}
|
|
|
|
|
|
|
|
as.str.WriteString(")")
|
|
|
|
|
|
|
|
}
|
2024-10-06 16:30:57 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitIfStmt(i *IfStmt) {
|
|
|
|
as.str.WriteString("(if ")
|
|
|
|
i.expr.accept(as)
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
i.then.accept(as)
|
|
|
|
if i.or != nil {
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
i.or.accept(as)
|
|
|
|
}
|
|
|
|
as.str.WriteString(")")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *AstStringer) visitEnvStmt(e *EnvStmt) {
|
|
|
|
as.str.WriteString("(env)")
|
|
|
|
}
|
2024-10-07 21:06:23 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitWhileStmt(w *WhileStmt) {
|
|
|
|
as.str.WriteString("(while ")
|
|
|
|
w.cond.accept(as)
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
w.body.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
}
|
2024-10-07 21:47:55 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitBreakStmt(b *BreakStmt) {
|
|
|
|
as.str.WriteString("(break)")
|
|
|
|
}
|
2024-10-09 23:36:18 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitFunStmt(f *FunStmt) {
|
|
|
|
as.str.WriteString(fmt.Sprintf("(fun %s", f.name.lexeme))
|
|
|
|
if len(f.args) != 0 {
|
|
|
|
as.str.WriteString("(")
|
2024-10-11 17:01:12 +03:00
|
|
|
for i, arg := range f.args {
|
2024-10-09 23:36:18 +03:00
|
|
|
as.str.WriteString(arg.lexeme)
|
2024-10-11 17:01:12 +03:00
|
|
|
if i < len(f.args)-1 {
|
|
|
|
as.str.WriteString(" ")
|
|
|
|
}
|
2024-10-09 23:36:18 +03:00
|
|
|
}
|
|
|
|
as.str.WriteString(")")
|
|
|
|
}
|
2024-10-11 17:01:12 +03:00
|
|
|
f.body.accept(as)
|
2024-10-09 23:36:18 +03:00
|
|
|
as.str.WriteString(")")
|
|
|
|
|
|
|
|
}
|
2024-10-11 17:01:12 +03:00
|
|
|
|
|
|
|
func (as *AstStringer) visitReturnStmt(r *ReturnStmt) {
|
|
|
|
as.str.WriteString("(return ")
|
|
|
|
r.value.accept(as)
|
|
|
|
as.str.WriteString(")")
|
|
|
|
}
|