Initial work on a Symbol Table abstraction

This commit is contained in:
Nemo 2020-07-08 19:56:28 +05:30
parent 66efa72230
commit 3b541898e2
7 changed files with 113 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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

48
compiler/symboltable.py Normal file
View File

@ -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)

View File

@ -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)

View File

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