Move AST nodes to their own files.

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2025-01-05 13:05:35 -08:00
parent 4acc09faf9
commit 5367fbd29d
9 changed files with 164 additions and 134 deletions

View file

@ -2,8 +2,6 @@ package ast
import ( import (
"bytes" "bytes"
"code.jmug.me/jmug/interpreter-in-go/pkg/token"
) )
type Node interface { type Node interface {
@ -39,135 +37,3 @@ func (p *Program) String() string {
} }
return out.String() return out.String()
} }
type LetStatement struct {
Token token.Token // TODO: This is a little redundant, figure out if I can get rid of it.
Name *Identifier
Value Expression
}
func (ls *LetStatement) statementNode() {}
func (ls *LetStatement) TokenLiteral() string {
return ls.Token.Literal
}
func (ls *LetStatement) String() string {
var out bytes.Buffer
out.WriteString(ls.TokenLiteral() + " ")
out.WriteString(ls.Name.String() + " = ")
if ls.Value != nil {
out.WriteString(ls.Value.String())
}
out.WriteString(";")
return out.String()
}
type ReturnStatement struct {
Token token.Token // TODO: This is a little redundant, figure out if I can get rid of it.
ReturnValue Expression
}
func (rs *ReturnStatement) statementNode() {}
func (rs *ReturnStatement) TokenLiteral() string {
return rs.Token.Literal
}
func (rs *ReturnStatement) String() string {
var out bytes.Buffer
out.WriteString(rs.TokenLiteral())
if rs.ReturnValue != nil {
out.WriteString(" " + rs.ReturnValue.String())
}
out.WriteString(";")
return out.String()
}
// ExpressionStatement is a simple wrapper of an expression in a statement
// This is common in scripting languages and allows you to have a source line
// that is solely an expression, think of the Python REPL and how you can
// type `1 + 1` and get a result.
type ExpressionStatement struct {
Token token.Token // The first token in the expression.
Expression Expression
}
func (es *ExpressionStatement) statementNode() {}
func (es *ExpressionStatement) TokenLiteral() string {
return es.Token.Literal
}
func (es *ExpressionStatement) String() string {
if es.Expression != nil {
return es.Expression.String()
}
return ""
}
// Identifier is treated as an expression because in certain
// circumstances they can return values (think `let some = other` where `other`
// is actually an expression returning a value) and this makes them easier to
// handle (according to the author).
type Identifier struct {
Token token.Token
Value string
}
func (i *Identifier) expressionNode() {}
func (i *Identifier) TokenLiteral() string {
return i.Token.Literal
}
func (i *Identifier) String() string {
return i.Value
}
type IntegerLiteral struct {
Token token.Token
Value int64
}
func (il *IntegerLiteral) expressionNode() {}
func (il *IntegerLiteral) TokenLiteral() string {
return il.Token.Literal
}
func (il *IntegerLiteral) String() string {
return il.Token.Literal
}
type PrefixExpression struct {
Token token.Token // The operator token
Operator string
Right Expression
}
func (pe *PrefixExpression) expressionNode() {}
func (pe *PrefixExpression) TokenLiteral() string {
return pe.Token.Literal
}
func (pe *PrefixExpression) String() string {
return "(" + pe.Operator + pe.Right.String() + ")"
}
type InfixExpression struct {
Token token.Token // The operator token
Operator string
Left Expression
Right Expression
}
func (ie *InfixExpression) expressionNode() {}
func (ie *InfixExpression) TokenLiteral() string {
return ie.Token.Literal
}
func (ie *InfixExpression) String() string {
return "(" + ie.Left.String() + " " + ie.Operator + " " + ie.Right.String() + ")"
}
type Boolean struct {
Token token.Token
Value bool
}
func (bl *Boolean) expressionNode() {}
func (bl *Boolean) TokenLiteral() string {
return bl.Token.Literal
}
func (bl *Boolean) String() string {
return bl.Token.Literal
}

16
pkg/ast/boolean.go Normal file
View file

@ -0,0 +1,16 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
type Boolean struct {
Token token.Token
Value bool
}
func (bl *Boolean) expressionNode() {}
func (bl *Boolean) TokenLiteral() string {
return bl.Token.Literal
}
func (bl *Boolean) String() string {
return bl.Token.Literal
}

View file

@ -0,0 +1,23 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
// ExpressionStatement is a simple wrapper of an expression in a statement
// This is common in scripting languages and allows you to have a source line
// that is solely an expression, think of the Python REPL and how you can
// type `1 + 1` and get a result.
type ExpressionStatement struct {
Token token.Token // The first token in the expression.
Expression Expression
}
func (es *ExpressionStatement) statementNode() {}
func (es *ExpressionStatement) TokenLiteral() string {
return es.Token.Literal
}
func (es *ExpressionStatement) String() string {
if es.Expression != nil {
return es.Expression.String()
}
return ""
}

20
pkg/ast/identifier.go Normal file
View file

@ -0,0 +1,20 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
// Identifier is treated as an expression because in certain
// circumstances they can return values (think `let some = other` where `other`
// is actually an expression returning a value) and this makes them easier to
// handle (according to the author).
type Identifier struct {
Token token.Token
Value string
}
func (i *Identifier) expressionNode() {}
func (i *Identifier) TokenLiteral() string {
return i.Token.Literal
}
func (i *Identifier) String() string {
return i.Value
}

View file

@ -0,0 +1,18 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
type InfixExpression struct {
Token token.Token // The operator token
Operator string
Left Expression
Right Expression
}
func (ie *InfixExpression) expressionNode() {}
func (ie *InfixExpression) TokenLiteral() string {
return ie.Token.Literal
}
func (ie *InfixExpression) String() string {
return "(" + ie.Left.String() + " " + ie.Operator + " " + ie.Right.String() + ")"
}

16
pkg/ast/integer.go Normal file
View file

@ -0,0 +1,16 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
type IntegerLiteral struct {
Token token.Token
Value int64
}
func (il *IntegerLiteral) expressionNode() {}
func (il *IntegerLiteral) TokenLiteral() string {
return il.Token.Literal
}
func (il *IntegerLiteral) String() string {
return il.Token.Literal
}

28
pkg/ast/let.go Normal file
View file

@ -0,0 +1,28 @@
package ast
import (
"bytes"
"code.jmug.me/jmug/interpreter-in-go/pkg/token"
)
type LetStatement struct {
Token token.Token // TODO: This is a little redundant, figure out if I can get rid of it.
Name *Identifier
Value Expression
}
func (ls *LetStatement) statementNode() {}
func (ls *LetStatement) TokenLiteral() string {
return ls.Token.Literal
}
func (ls *LetStatement) String() string {
var out bytes.Buffer
out.WriteString(ls.TokenLiteral() + " ")
out.WriteString(ls.Name.String() + " = ")
if ls.Value != nil {
out.WriteString(ls.Value.String())
}
out.WriteString(";")
return out.String()
}

View file

@ -0,0 +1,17 @@
package ast
import "code.jmug.me/jmug/interpreter-in-go/pkg/token"
type PrefixExpression struct {
Token token.Token // The operator token
Operator string
Right Expression
}
func (pe *PrefixExpression) expressionNode() {}
func (pe *PrefixExpression) TokenLiteral() string {
return pe.Token.Literal
}
func (pe *PrefixExpression) String() string {
return "(" + pe.Operator + pe.Right.String() + ")"
}

26
pkg/ast/return.go Normal file
View file

@ -0,0 +1,26 @@
package ast
import (
"bytes"
"code.jmug.me/jmug/interpreter-in-go/pkg/token"
)
type ReturnStatement struct {
Token token.Token // TODO: This is a little redundant, figure out if I can get rid of it.
ReturnValue Expression
}
func (rs *ReturnStatement) statementNode() {}
func (rs *ReturnStatement) TokenLiteral() string {
return rs.Token.Literal
}
func (rs *ReturnStatement) String() string {
var out bytes.Buffer
out.WriteString(rs.TokenLiteral())
if rs.ReturnValue != nil {
out.WriteString(" " + rs.ReturnValue.String())
}
out.WriteString(";")
return out.String()
}