restructure
This commit is contained in:
parent
edcbfde351
commit
eebaadc16e
21 changed files with 937 additions and 626 deletions
55
ast/ast.go
Normal file
55
ast/ast.go
Normal 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
66
ast/astprinter.go
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue