-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ce925fd
Showing
10 changed files
with
1,762 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
package ast | ||
|
||
import ( | ||
"bytes" | ||
"flare/token" | ||
"strings" | ||
) | ||
|
||
type Node interface { | ||
TokenLiteral() string | ||
String() string | ||
} | ||
|
||
type Statement interface { | ||
Node | ||
statementNode() | ||
} | ||
|
||
type Expression interface { | ||
Node | ||
expressionNode() | ||
} | ||
|
||
type Program struct { | ||
Statements []Statement | ||
} | ||
|
||
type Identifier struct { | ||
Token token.Token | ||
Value string | ||
} | ||
|
||
type LetStatement struct { | ||
Token token.Token | ||
Name *Identifier | ||
Value Expression | ||
} | ||
|
||
type ReturnStatement struct { | ||
Token token.Token | ||
ReturnValue Expression | ||
} | ||
|
||
type ExpressionStatement struct { | ||
Token token.Token | ||
Expression Expression | ||
} | ||
|
||
type IntegerLiteral struct { | ||
Token token.Token | ||
Value int64 | ||
} | ||
|
||
type PrefixExpression struct { | ||
Token token.Token | ||
Operator string | ||
Right Expression | ||
} | ||
|
||
type InfixExpression struct { | ||
Token token.Token | ||
Left Expression | ||
Operator string | ||
Right Expression | ||
} | ||
|
||
type Boolean struct { | ||
Token token.Token | ||
Value bool | ||
} | ||
|
||
type IfExpression struct { | ||
Token token.Token | ||
Condition Expression | ||
Consequence *BlockStatement | ||
Alternative *BlockStatement | ||
} | ||
|
||
type BlockStatement struct { | ||
Token token.Token | ||
Statements []Statement | ||
} | ||
|
||
type FunctionLiteral struct { | ||
Token token.Token | ||
Parameters []*Identifier | ||
Body *BlockStatement | ||
} | ||
|
||
type CallExpression struct { | ||
Token token.Token | ||
Function Expression | ||
Arguments []Expression | ||
} | ||
|
||
func (ls *LetStatement) statementNode() {} | ||
func (ls *LetStatement) TokenLiteral() string { return ls.Token.Literal } | ||
|
||
func (i *Identifier) expressionNode() {} | ||
func (i *Identifier) String() string { return i.Value } | ||
func (i *Identifier) TokenLiteral() string { return i.Token.Literal } | ||
|
||
func (rs *ReturnStatement) statementNode() {} | ||
func (rs *ReturnStatement) TokenLiteral() string { return rs.Token.Literal } | ||
|
||
func (es *ExpressionStatement) statementNode() {} | ||
func (es *ExpressionStatement) TokenLiteral() string { return es.Token.Literal } | ||
|
||
func (il *IntegerLiteral) expressionNode() {} | ||
func (il *IntegerLiteral) TokenLiteral() string { return il.Token.Literal } | ||
func (il *IntegerLiteral) String() string { return il.Token.Literal } | ||
|
||
func (pe *PrefixExpression) expressionNode() {} | ||
func (pe *PrefixExpression) TokenLiteral() string { return pe.Token.Literal } | ||
func (pe *PrefixExpression) String() string { | ||
var out bytes.Buffer | ||
|
||
out.WriteString("(") | ||
out.WriteString(pe.Operator) | ||
out.WriteString(pe.Right.String()) | ||
out.WriteString(")") | ||
|
||
return out.String() | ||
} | ||
|
||
func (oe *InfixExpression) expressionNode() {} | ||
func (oe *InfixExpression) TokenLiteral() string { return oe.Token.Literal } | ||
func (oe *InfixExpression) String() string { | ||
var out bytes.Buffer | ||
|
||
out.WriteString("(") | ||
out.WriteString(oe.Left.String()) | ||
out.WriteString(" " + oe.Operator + " ") | ||
out.WriteString(oe.Right.String()) | ||
out.WriteString(")") | ||
|
||
return out.String() | ||
} | ||
|
||
func (b *Boolean) expressionNode() {} | ||
func (b *Boolean) TokenLiteral() string { return b.Token.Literal } | ||
func (b *Boolean) String() string { return b.Token.Literal } | ||
|
||
func (p *Program) TokenLiteral() string { | ||
if len(p.Statements) > 0 { | ||
return p.Statements[0].TokenLiteral() | ||
} else { | ||
return "" | ||
} | ||
} | ||
|
||
func (ie *IfExpression) expressionNode() {} | ||
func (ie *IfExpression) TokenLiteral() string { return ie.Token.Literal } | ||
func (ie *IfExpression) String() string { | ||
var out bytes.Buffer | ||
|
||
out.WriteString("if") | ||
out.WriteString(ie.Condition.String()) | ||
out.WriteString(" ") | ||
out.WriteString(ie.Consequence.String()) | ||
|
||
if ie.Alternative != nil { | ||
out.WriteString("else ") | ||
out.WriteString(ie.Alternative.String()) | ||
} | ||
|
||
return out.String() | ||
} | ||
|
||
func (bs *BlockStatement) statementNode() {} | ||
func (bs *BlockStatement) TokenLiteral() string { return bs.Token.Literal } | ||
func (bs *BlockStatement) String() string { | ||
var out bytes.Buffer | ||
|
||
for _, s := range bs.Statements { | ||
out.WriteString(s.String()) | ||
} | ||
|
||
return out.String() | ||
} | ||
|
||
func (fl *FunctionLiteral) expressionNode() {} | ||
func (fl *FunctionLiteral) TokenLiteral() string { return fl.Token.Literal } | ||
func (fl *FunctionLiteral) String() string { | ||
var out bytes.Buffer | ||
|
||
params := []string{} | ||
|
||
for _, p := range fl.Parameters { | ||
params = append(params, p.String()) | ||
} | ||
|
||
out.WriteString(fl.TokenLiteral()) | ||
out.WriteString("(") | ||
out.WriteString(strings.Join(params, ", ")) | ||
out.WriteString(") ") | ||
out.WriteString(fl.Body.String()) | ||
|
||
return out.String() | ||
} | ||
|
||
func (ce *CallExpression) expressionNode() {} | ||
func (ce *CallExpression) TokenLiteral() string { return ce.Token.Literal } | ||
func (ce *CallExpression) String() string { | ||
var out bytes.Buffer | ||
args := []string{} | ||
|
||
for _, a := range ce.Arguments { | ||
args = append(args, a.String()) | ||
} | ||
|
||
out.WriteString(ce.Function.String()) | ||
out.WriteString("(") | ||
out.WriteString(strings.Join(args, ", ")) | ||
out.WriteString(")") | ||
|
||
return out.String() | ||
} | ||
|
||
func (p *Program) String() string { | ||
var out bytes.Buffer | ||
|
||
for _, s := range p.Statements { | ||
out.WriteString(s.String()) | ||
} | ||
|
||
return out.String() | ||
} | ||
|
||
func (ls *LetStatement) String() string { | ||
var out bytes.Buffer | ||
|
||
out.WriteString(ls.TokenLiteral() + " ") | ||
out.WriteString(ls.Name.String()) | ||
out.WriteString(" = ") | ||
|
||
if ls.Value != nil { | ||
out.WriteString(ls.Value.String()) | ||
} | ||
|
||
out.WriteString(";") | ||
|
||
return out.String() | ||
} | ||
|
||
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() | ||
} | ||
|
||
func (es *ExpressionStatement) String() string { | ||
if es.Expression != nil { | ||
return es.Expression.String() | ||
} | ||
|
||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package ast | ||
|
||
import ( | ||
"flare/token" | ||
"testing" | ||
) | ||
|
||
func TestString(t *testing.T) { | ||
program := &Program{ | ||
Statements: []Statement{ | ||
&LetStatement{ | ||
Token: token.Token{Type: token.LET, Literal: "let"}, | ||
Name: &Identifier{ | ||
Token: token.Token{Type: token.IDENT, Literal: "myVar"}, | ||
Value: "myVar", | ||
}, | ||
Value: &Identifier{ | ||
Token: token.Token{Type: token.IDENT, Literal: "anotherVar"}, | ||
Value: "anotherVar", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
if program.String() != "let myVar = anotherVar;" { | ||
t.Errorf("program.String() wrong. got=%q", program.String()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module flare | ||
|
||
go 1.23.2 |
Oops, something went wrong.