diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index 51c78c0..62e26fd 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -2,8 +2,6 @@ package ast import ( "bytes" - - "code.jmug.me/jmug/interpreter-in-go/pkg/token" ) type Node interface { @@ -39,135 +37,3 @@ func (p *Program) String() 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 -} diff --git a/pkg/ast/boolean.go b/pkg/ast/boolean.go new file mode 100644 index 0000000..256cde5 --- /dev/null +++ b/pkg/ast/boolean.go @@ -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 +} diff --git a/pkg/ast/expression_statement.go b/pkg/ast/expression_statement.go new file mode 100644 index 0000000..4766371 --- /dev/null +++ b/pkg/ast/expression_statement.go @@ -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 "" +} diff --git a/pkg/ast/identifier.go b/pkg/ast/identifier.go new file mode 100644 index 0000000..4635ddc --- /dev/null +++ b/pkg/ast/identifier.go @@ -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 +} diff --git a/pkg/ast/infix_expression.go b/pkg/ast/infix_expression.go new file mode 100644 index 0000000..53d4bf9 --- /dev/null +++ b/pkg/ast/infix_expression.go @@ -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() + ")" +} diff --git a/pkg/ast/integer.go b/pkg/ast/integer.go new file mode 100644 index 0000000..4a04bef --- /dev/null +++ b/pkg/ast/integer.go @@ -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 +} diff --git a/pkg/ast/let.go b/pkg/ast/let.go new file mode 100644 index 0000000..4f13337 --- /dev/null +++ b/pkg/ast/let.go @@ -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() +} diff --git a/pkg/ast/prefix_expression.go b/pkg/ast/prefix_expression.go new file mode 100644 index 0000000..942f0cf --- /dev/null +++ b/pkg/ast/prefix_expression.go @@ -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() + ")" +} diff --git a/pkg/ast/return.go b/pkg/ast/return.go new file mode 100644 index 0000000..1fa7101 --- /dev/null +++ b/pkg/ast/return.go @@ -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() +}