Skip to content

Commit

Permalink
refactor: rewrite lexer
Browse files Browse the repository at this point in the history
  • Loading branch information
siyul-park committed Feb 17, 2025
1 parent eb694b3 commit 23184a8
Show file tree
Hide file tree
Showing 12 changed files with 678 additions and 695 deletions.
8 changes: 1 addition & 7 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"io"
"log"
"os"

Expand Down Expand Up @@ -41,12 +40,7 @@ func runFile(filePath string, printBytecode bool) {
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
log.Fatal("Error reading file: ", err)
}

l := lexer.New(string(data))
l := lexer.New(file)
p := parser.New(l)

program, err := p.Parse()
Expand Down
6 changes: 0 additions & 6 deletions internal/bytecode/bytecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ func (b *Bytecode) Add(instructions ...Instruction) int {
return offset
}

func (b *Bytecode) Replace(offset int, instruction Instruction) {
for i := 0; i < len(instruction) && offset+i < len(b.Instructions); i++ {
b.Instructions[offset+i] = instruction[i]
}
}

func (b *Bytecode) Store(constants []byte) int {
offset := len(b.Constants)
b.Constants = append(b.Constants, constants...)
Expand Down
60 changes: 30 additions & 30 deletions internal/compiler/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ import (
)

type Analyzer struct {
meta map[ast.Node]*Meta
semantic map[ast.Node]*Semantic
}

type Meta struct {
type Semantic struct {
Kind interpreter.Kind
}

func NewAnalyzer() *Analyzer {
return &Analyzer{meta: make(map[ast.Node]*Meta)}
return &Analyzer{semantic: make(map[ast.Node]*Semantic)}
}

func (a *Analyzer) Analyze(node ast.Node) *Meta {
if meta, found := a.meta[node]; found {
return meta
func (a *Analyzer) Analyze(node ast.Node) *Semantic {
if sem, found := a.semantic[node]; found {
return sem
}

var meta *Meta
var meta *Semantic
switch node := node.(type) {
case *ast.Program:
meta = a.program(node)
Expand All @@ -49,45 +49,45 @@ func (a *Analyzer) Analyze(node ast.Node) *Meta {
meta = nil
}

a.meta[node] = meta
a.semantic[node] = meta
return meta
}

func (a *Analyzer) Close() {
a.meta = make(map[ast.Node]*Meta)
a.semantic = make(map[ast.Node]*Semantic)
}

func (a *Analyzer) program(node *ast.Program) *Meta {
func (a *Analyzer) program(node *ast.Program) *Semantic {
for _, stmt := range node.Statements {
a.Analyze(stmt)
}
return &Meta{Kind: interpreter.KindVoid}
return &Semantic{Kind: interpreter.KindVoid}
}

func (a *Analyzer) emptyStatement(_ *ast.EmptyStatement) *Meta {
return &Meta{Kind: interpreter.KindVoid}
func (a *Analyzer) emptyStatement(_ *ast.EmptyStatement) *Semantic {
return &Semantic{Kind: interpreter.KindVoid}
}

func (a *Analyzer) blockStatement(node *ast.BlockStatement) *Meta {
func (a *Analyzer) blockStatement(node *ast.BlockStatement) *Semantic {
for _, stmt := range node.Statements {
a.Analyze(stmt)
}
return &Meta{Kind: interpreter.KindVoid}
return &Semantic{Kind: interpreter.KindVoid}
}

func (a *Analyzer) expressionStatement(node *ast.ExpressionStatement) *Meta {
func (a *Analyzer) expressionStatement(node *ast.ExpressionStatement) *Semantic {
a.Analyze(node.Expression)
return &Meta{Kind: interpreter.KindVoid}
return &Semantic{Kind: interpreter.KindVoid}
}

func (a *Analyzer) prefixExpression(node *ast.PrefixExpression) *Meta {
func (a *Analyzer) prefixExpression(node *ast.PrefixExpression) *Semantic {
right := a.Analyze(node.Right)
if right == nil {
return nil
}

kind := interpreter.KindUnknown
switch node.Token {
switch node.Token.Type {
case token.PLUS, token.MINUS:
switch right.Kind {
case interpreter.KindBool:
Expand All @@ -100,15 +100,15 @@ func (a *Analyzer) prefixExpression(node *ast.PrefixExpression) *Meta {
}
default:
}
return &Meta{Kind: kind}
return &Semantic{Kind: kind}
}

func (a *Analyzer) infixExpression(node *ast.InfixExpression) *Meta {
func (a *Analyzer) infixExpression(node *ast.InfixExpression) *Semantic {
left := a.Analyze(node.Left)
right := a.Analyze(node.Right)

kind := interpreter.KindUnknown
switch node.Token {
switch node.Token.Type {
case token.PLUS:
if left.Kind == interpreter.KindString || right.Kind == interpreter.KindString {
kind = interpreter.KindString
Expand All @@ -117,7 +117,7 @@ func (a *Analyzer) infixExpression(node *ast.InfixExpression) *Meta {
} else {
kind = interpreter.KindInt32
}
case token.DIVIDE, token.MODULO:
case token.DIVIDE, token.MODULUS:
kind = interpreter.KindFloat64
default:
if left.Kind == interpreter.KindInt32 && right.Kind == interpreter.KindInt32 {
Expand All @@ -126,23 +126,23 @@ func (a *Analyzer) infixExpression(node *ast.InfixExpression) *Meta {
kind = interpreter.KindFloat64
}
}
return &Meta{Kind: kind}
return &Semantic{Kind: kind}
}

func (a *Analyzer) boolLiteral(_ *ast.BoolLiteral) *Meta {
return &Meta{Kind: interpreter.KindBool}
func (a *Analyzer) boolLiteral(_ *ast.BoolLiteral) *Semantic {
return &Semantic{Kind: interpreter.KindBool}
}

func (a *Analyzer) numberLiteral(node *ast.NumberLiteral) *Meta {
func (a *Analyzer) numberLiteral(node *ast.NumberLiteral) *Semantic {
kind := interpreter.KindInt32
if strings.Contains(node.Token.Literal, ".") || strings.Contains(node.Token.Literal, "e") {
kind = interpreter.KindFloat64
} else if node.Value != float64(int32(node.Value)) {
kind = interpreter.KindFloat64
}
return &Meta{Kind: kind}
return &Semantic{Kind: kind}
}

func (a *Analyzer) stringLiteral(_ *ast.StringLiteral) *Meta {
return &Meta{Kind: interpreter.KindString}
func (a *Analyzer) stringLiteral(_ *ast.StringLiteral) *Semantic {
return &Semantic{Kind: interpreter.KindString}
}
82 changes: 41 additions & 41 deletions internal/compiler/analyzer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,164 +13,164 @@ import (
func TestAnalyzer_Analyze(t *testing.T) {
tests := []struct {
node ast.Node
meta *Meta
meta *Semantic
}{
{
node: ast.NewProgram(),
meta: &Meta{Kind: interpreter.KindVoid},
meta: &Semantic{Kind: interpreter.KindVoid},
},
{
node: ast.NewEmptyStatement(),
meta: &Meta{Kind: interpreter.KindVoid},
meta: &Semantic{Kind: interpreter.KindVoid},
},
{
node: ast.NewBlockStatement(),
meta: &Meta{Kind: interpreter.KindVoid},
meta: &Semantic{Kind: interpreter.KindVoid},
},
{
node: ast.NewExpressionStatement(
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
),
meta: &Meta{Kind: interpreter.KindVoid},
meta: &Semantic{Kind: interpreter.KindVoid},
},
{
node: ast.NewPrefixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
),
meta: &Meta{Kind: interpreter.KindInt32},
meta: &Semantic{Kind: interpreter.KindInt32},
},
{
node: ast.NewPrefixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1.5"}, 1.5),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewPrefixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewStringLiteral(token.Token{Type: token.STRING, Literal: "foo"}, "foo"),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewPrefixExpression(
token.MINUS,
token.New(token.MINUS, "-"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
),
meta: &Meta{Kind: interpreter.KindInt32},
meta: &Semantic{Kind: interpreter.KindInt32},
},
{
node: ast.NewPrefixExpression(
token.MINUS,
token.New(token.MINUS, "-"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2.0"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2"}, 2),
),
meta: &Meta{Kind: interpreter.KindInt32},
meta: &Semantic{Kind: interpreter.KindInt32},
},
{
node: ast.NewInfixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2.0"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.PLUS,
token.New(token.PLUS, "+"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewStringLiteral(token.Token{Type: token.STRING, Literal: "2"}, "2"),
),
meta: &Meta{Kind: interpreter.KindString},
meta: &Semantic{Kind: interpreter.KindString},
},
{
node: ast.NewInfixExpression(
token.MINUS,
token.New(token.MINUS, "-"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2"}, 2),
),
meta: &Meta{Kind: interpreter.KindInt32},
meta: &Semantic{Kind: interpreter.KindInt32},
},
{
node: ast.NewInfixExpression(
token.MULTIPLE,
token.New(token.MULTIPLY, "*"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2"}, 2),
),
meta: &Meta{Kind: interpreter.KindInt32},
meta: &Semantic{Kind: interpreter.KindInt32},
},
{
node: ast.NewInfixExpression(
token.MULTIPLE,
token.New(token.MULTIPLY, "*"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2.0"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.MULTIPLE,
token.New(token.MULTIPLY, "*"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewStringLiteral(token.Token{Type: token.STRING, Literal: "2"}, "2"),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.DIVIDE,
token.New(token.DIVIDE, "/"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.DIVIDE,
token.New(token.DIVIDE, "/"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 2),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2.0"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.DIVIDE,
token.New(token.DIVIDE, "/"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewStringLiteral(token.Token{Type: token.STRING, Literal: "2"}, "2"),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.MODULO,
token.New(token.MODULUS, "%"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.MODULO,
token.New(token.MODULUS, "%"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 2),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "2.0"}, 2),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
{
node: ast.NewInfixExpression(
token.MODULO,
token.New(token.MODULUS, "%"),
ast.NewNumberLiteral(token.Token{Type: token.NUMBER, Literal: "1"}, 1),
ast.NewStringLiteral(token.Token{Type: token.STRING, Literal: "2"}, "2"),
),
meta: &Meta{Kind: interpreter.KindFloat64},
meta: &Semantic{Kind: interpreter.KindFloat64},
},
}

Expand Down
Loading

0 comments on commit 23184a8

Please sign in to comment.