Initial work on a Symbol Table abstraction

master
Nemo 2 years ago
parent 66efa72230
commit 3b541898e2
  1. 8
      compiler/constants.py
  2. 2
      compiler/engine.py
  3. 2
      compiler/grammar.py
  4. 5
      compiler/main.py
  5. 48
      compiler/symboltable.py
  6. 53
      compiler/symboltable_test.py
  7. 2
      compiler/tokenizer.py

@ -1,4 +1,4 @@
from enum import IntFlag,auto
from enum import IntFlag,auto,Enum
class PrintableFlag(IntFlag):
def __repr__(self):
@ -106,3 +106,9 @@ class Token(PrintableFlag):
STRINGCONSTANT = Atom.STRINGCONSTANT.value
SYMBOL = auto()
KEYWORD = auto()
class SymbolType(Enum):
STATIC = auto()
FIELD = auto()
ARG = auto()
VAR = auto()

@ -1,5 +1,5 @@
from tokenizer import JackTokenizer
from keywords import *
from constants import *
from grammar import *
import sys

@ -1,4 +1,4 @@
from keywords import Atom
from constants import Atom
"""
The grammar is defined by the following constructs:

@ -2,12 +2,11 @@ from engine import Engine
import sys
from pathlib import Path
if __name__ == '__main__':
if __name__ == '__main__' and len(sys.argv) > 1:
p = Path(sys.argv[1])
if p.is_dir():
for f in p.glob("*.jack"):
print("compiling %s" % f)
Engine(f.as_posix()).compileClass()
elif p.is_file():
Engine(p.as_posix()).compileClass()
Engine(p.as_posix()).compileClass()

@ -0,0 +1,48 @@
from constants import SymbolType
class SymbolTable:
def __init__(self):
self.subroutineTable = {}
self.classTable = {}
self.subroutineIndex = 0
self.classIndex = 0
def startSubroutine(self):
self.subroutineTable = {}
def define(self, name, var_type, kind):
if (kind in [SymbolType.STATIC, SymbolType.FIELD]):
self.classTable[name] = (var_type, kind, self.classIndex)
self.classIndex += 1
elif (kind in [SymbolType.ARG, SymbolType.VAR]):
self.subroutineTable[name] = (var_type, kind, self.subroutineIndex)
self.subroutineIndex += 1
else:
raise Exception("Invalid SymbolType")
def varCount(self, kind):
t = None
if (kind in [SymbolType.STATIC, SymbolType.FIELD]):
t = self.classTable
elif (kind in [SymbolType.ARG, SymbolType.VAR]):
t = self.subroutineTable
else:
raise Exception("Invalid SymbolType")
return len([i for i in t.values() if i[1] == kind])
def _lookup(self, name, index):
if name in self.classTable:
return self.classTable[name][index]
elif name in self.subroutineTable:
return self.subroutineTable[name][index]
else:
raise Exception("Invalid variable name")
def TypeOf(self, name):
return self._lookup(name, 0)
def KindOf(self, name):
return self._lookup(name, 1)
def IndexOf(self, name):
return self._lookup(name, 2)

@ -0,0 +1,53 @@
from symboltable import SymbolTable
from constants import SymbolType
def test_st_init():
st = SymbolTable()
assert(st.subroutineTable == {})
assert(st.classTable == {})
def test_st_define():
st = SymbolTable()
st.define("first", "int", SymbolType.STATIC)
st.define("second", "SomeClass", SymbolType.FIELD)
st.define("third", "String", SymbolType.ARG)
st.define("fourth", "bool", SymbolType.VAR)
assert(st.classTable == {
"first": ("int", SymbolType.STATIC, 0),
"second": ("SomeClass", SymbolType.FIELD, 1),
})
assert(st.subroutineTable == {
"third": ("String", SymbolType.ARG, 0),
"fourth": ("bool", SymbolType.VAR, 1),
})
def test_subroutine():
st = SymbolTable()
st.define("first", "int", SymbolType.ARG)
st.startSubroutine()
assert(st.subroutineTable == {})
def test_var_count():
st = SymbolTable()
st.define("first", "int", SymbolType.STATIC)
st.define("second", "SomeClass", SymbolType.FIELD)
st.define("third", "String", SymbolType.ARG)
st.define("fourth", "bool", SymbolType.VAR)
assert(st.varCount(SymbolType.STATIC) == 1)
assert(st.varCount(SymbolType.FIELD) == 1)
assert(st.varCount(SymbolType.ARG) == 1)
assert(st.varCount(SymbolType.VAR) == 1)
def test_lookups():
st = SymbolTable()
st.define("first", "int", SymbolType.STATIC)
st.define("second", "SomeClass", SymbolType.FIELD)
st.define("third", "String", SymbolType.ARG)
st.define("fourth", "bool", SymbolType.VAR)
assert(st.KindOf("first") == SymbolType.STATIC)
assert(st.TypeOf("second") == "SomeClass")
assert(st.IndexOf("third") == 0)
assert(st.IndexOf("fourth") == 1)

@ -1,5 +1,5 @@
import re
from keywords import *
from constants import *
from html import escape
from enum import Enum
# Superclass in some sense

Loading…
Cancel
Save