restructure

This commit is contained in:
basil 2025-06-08 15:02:35 -04:00
parent edcbfde351
commit eebaadc16e
Signed by: basil
SSH key fingerprint: SHA256:y04xIFL/yqNaG9ae9Vl95vELtHfApGAIoOGLeVLP/fE
21 changed files with 937 additions and 626 deletions

55
ast/ast.go Normal file
View file

@ -0,0 +1,55 @@
package ast
import "git.red-panda.pet/pandaware/lox-go/lexer"
// todo: find something better than any here
// we can't use generics on either the visitor itself or
// each individual method because the adding it to the
// visitor itself infects every expr you use with it
// and methods cannot have generic parameters
type ExprVisitor interface {
VisitBinaryExpr(b *BinaryExpr) any
VisitGroupingExpr(g *GroupingExpr) any
VisitLiteralExpr(g *LiteralExpr) any
VisitUnaryExpr(g *UnaryExpr) any
}
type Expr interface {
accept(v ExprVisitor) any
}
type BinaryExpr struct {
Left Expr
Operator *lexer.Token
Right Expr
}
func (b *BinaryExpr) accept(v ExprVisitor) any {
return v.VisitBinaryExpr(b)
}
type GroupingExpr struct {
Expr Expr
}
func (g *GroupingExpr) accept(v ExprVisitor) any {
return v.VisitGroupingExpr(g)
}
type LiteralExpr struct {
Value any
}
func (l *LiteralExpr) accept(v ExprVisitor) any {
return v.VisitLiteralExpr(l)
}
type UnaryExpr struct {
Operator *lexer.Token
Right Expr
}
func (u *UnaryExpr) accept(v ExprVisitor) any {
return v.VisitUnaryExpr(u)
}

66
ast/astprinter.go Normal file
View file

@ -0,0 +1,66 @@
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
}