85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
from operator import le
|
|
from SymbolTable import SymbolTable
|
|
from Hashtable import HashTable
|
|
import re
|
|
|
|
class Scanner:
|
|
def __init__(self, tokensPath):
|
|
self.tokensPath = tokensPath
|
|
self.symbolTable = SymbolTable()
|
|
self.indentifierRegex = r"^[a-zA-Z][a-zA-Z0-9]*$"
|
|
self.constantRegex = r"^0$|^[1-9][0-9]*$|^-[1-9][0-9]*$"
|
|
self.tokens = []
|
|
self.pif = {}
|
|
self.readTokens()
|
|
|
|
def readTokens(self):
|
|
with open(self.tokensPath, "r") as file:
|
|
isKeyword = True
|
|
isOperator = False
|
|
for line in file:
|
|
self.tokens.append(line.strip())
|
|
self.tokensRegex = '|'.join(map(re.escape, self.tokens))
|
|
|
|
def isIdentifier(self, token):
|
|
return re.match(self.indentifierRegex, token)
|
|
|
|
def isConstant(self, token):
|
|
return re.match(self.constantRegex, token)
|
|
|
|
def isToken(self, token):
|
|
return token in self.tokens
|
|
|
|
def scan(self, codePath):
|
|
with open(codePath, "r") as file:
|
|
identifierCounter = 1
|
|
constantCounter = 1
|
|
lineCounter = 0
|
|
try:
|
|
for line in file:
|
|
line = line.strip()
|
|
tokens = re.findall(self.tokensRegex + r"|\w+", line)
|
|
for token in tokens:
|
|
if self.isToken(token):
|
|
self.pif[token] = -1
|
|
elif self.isIdentifier(token):
|
|
position = self.symbolTable.getPositionIdentifier(token)
|
|
if position is None:
|
|
self.symbolTable.addIdentifier(token, identifierCounter)
|
|
self.pif["Identifier"] = identifierCounter
|
|
identifierCounter += 1
|
|
else:
|
|
self.pif["Identifier"] = position[1]
|
|
elif self.isConstant(token):
|
|
position = self.symbolTable.getPositionConstants(token)
|
|
if position is None:
|
|
self.symbolTable.addConstants(token, constantCounter)
|
|
self.pif['Constant'] = constantCounter
|
|
constantCounter += 1
|
|
else:
|
|
self.pif["Constant"] = position[1]
|
|
else:
|
|
raise Exception(f"Invalid token {token} at line {lineCounter}")
|
|
lineCounter += 1
|
|
print("Lexically correct")
|
|
except Exception as e:
|
|
print(e)
|
|
return
|
|
|
|
|
|
def main():
|
|
scanner = Scanner("tokens.in")
|
|
scanner.scan("p1error.in")
|
|
#save output to file
|
|
with open("PIF.out", "w") as file:
|
|
for key in scanner.pif:
|
|
file.write(f"{key} -> {scanner.pif[key]}\n")
|
|
|
|
with open("ST.out", "w") as file:
|
|
file.write(str(scanner.symbolTable))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|