Skip to content

Commit

Permalink
adding start of SymbolTable
Browse files Browse the repository at this point in the history
  • Loading branch information
Isaiah Becker-Mayer committed Mar 28, 2021
1 parent c834139 commit 0cba23c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Compiler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func main() {

// for each jack file
for _, filePath := range files {
ce, err := compiler.New(filePath)
ce, err := compiler.NewCompilationEngine(filePath)
err = ce.Run()
if err != nil {
panic(err)
Expand Down
4 changes: 2 additions & 2 deletions Compiler/pkg/compiler/compilationengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ type CompilationEngine struct {
xmlEnc *xml.Encoder // The xml encoder for testing
}

// New takes in a path to a jack file and returns an initialized CompilationEngine
// NewCompilationEngine takes in a path to a jack file and returns an initialized CompilationEngine
// ready to compile it.
func New(jackFilePath string) (*CompilationEngine, error) {
func NewCompilationEngine(jackFilePath string) (*CompilationEngine, error) {
ce := &CompilationEngine{
jackFilePath: jackFilePath,
}
Expand Down
121 changes: 121 additions & 0 deletions Compiler/pkg/compiler/symboltable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package compiler

import "fmt"

type Kind string

const (
KIND_STATIC Kind = "static"
KIND_FIELD Kind = "field"
KIND_ARG Kind = "arg"
KIND_VAR Kind = "var"
KIND_NONE Kind = "none"
)

// Entry is an entry in the symbol table
type Entry struct {
// Name is the identifier name
Name string
// Type is the identifier type
Type string
// Kind is the kind of the identifier (see constants of prefix "KIND_")
Kind Kind
// Index is the index assigned to the identifier in the current scope
Index uint
}

// symTable is the actual table mapping symbol names to their corresponding entry
type symTable map[string]Entry

// SymbolTable associates the identifier names found in the program with identifier properties needed for compilation.
// The SymbolTable has two nested scopes: class/subroutine
type SymbolTable struct {
// table is where the class table and subroutine tables themselves are stored, in a map from Kind to *symTable.
// Kind can be used to distinguish between class and subroutine scopes: KIND_STATIC and KIND_FIELD belong to the
// class table, and KIND_ARG and KIND_VAR belong to the subroutine table. Storing the tables like this allows for
// simpler and more concise class methods
table map[Kind]*symTable
// varCount is a map between each Kind and the number of variables of the given Kind defined in the current scope
varCount map[Kind]uint
}

// NewSymbolTable creates a new empty symbol table
func NewSymbolTable() *SymbolTable {
classTable := make(symTable)
subroutineTable := make(symTable)

return &SymbolTable{
table: map[Kind]*symTable{
KIND_STATIC: &classTable,
KIND_FIELD: &classTable,
KIND_ARG: &subroutineTable,
KIND_VAR: &subroutineTable,
},

varCount: map[Kind]uint{
KIND_STATIC: 0,
KIND_FIELD: 0,
KIND_ARG: 0,
KIND_VAR: 0,
},
}
}

// StartSubroutine starts a new subroutine, i.e. resets the SubroutineTable
func (s *SymbolTable) StartSubroutine() {
subroutineTable := make(symTable)
s.table[KIND_ARG] = &subroutineTable
s.table[KIND_VAR] = &subroutineTable
s.varCount[KIND_ARG] = 0
s.varCount[KIND_VAR] = 0
}

// Define defines a new entry in the symbol table
func (s *SymbolTable) Define(name, type_ string, kind Kind) error {
table := *(s.table[kind])

// check if this symbol is already defined in the given scope
_, ok := table[name]
if ok {
return fmt.Errorf("attempted redefinition of symbol: %v", name)
}

// add entry
table[name] = Entry{
Name: name,
Type: type_,
Kind: kind,
Index: s.varCount[kind],
}

// increment varCount for this type
s.varCount[kind]++

return nil
}

// VarCount returns the number of variables of the given kind already defined in the current scope
func (s *SymbolTable) VarCount(kind Kind) uint {
return s.varCount[kind]
}

func (s *SymbolTable) KindOf(name string) Kind {
var kind Kind
subroutineTable := *s.table[KIND_ARG]
classTable := *s.table[KIND_STATIC]

// Check subroutine scope first
kind = subroutineTable[name].Kind
if kind != "" {
return kind
}

// If nothing was found, check class scope
kind = classTable[name].Kind
if kind != "" {
return kind
}

// If nothing was found in either table return KIND_NONE
return KIND_NONE
}
2 changes: 1 addition & 1 deletion Compiler/test/compilationengine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func runCeTest(jackFilePath string, t *testing.T) {
ce, err := compiler.New(jackFilePath)
ce, err := compiler.NewCompilationEngine(jackFilePath)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 0cba23c

Please sign in to comment.