class Assign: def __init__(self): self.id = None self.expr = None #Simple parsing for Assign def parse(self): self.id = Id() self.id.parse(TokList.getIdOrConst()) TokList.nextToken() TokList.match('ASSIGN', 'assign') self.expr = Expr() self.expr.parse() TokList.match('SEMICOLON', 'assign') #Simple printing for Assign def print(self): TokList.printIndent() self.id.print() print(':=', end='') self.expr.print() print(';') #Executor that determines value of an expression and then sets that value to the respective Id def exec(self): val = self.expr.exec() self.id.setValue(val)
class IdList: def __init__(self): self.id = None self.id_list = None #Simple parsing to check for further ids def parse(self): self.id = Id() #Passing in name of id to the parse function self.id.parse(TokList.getIdOrConst()) TokList.nextToken() if TokList.checkTok('COMMA'): TokList.match('COMMA', 'id list') self.id_list = IdList() self.id_list.parse() #Simple printing def print(self): self.id.print() if (self.id_list is not None): print(',', end='') self.id_list.print() def exec(self): pass #Used to set the values of all variables in an Id List, init determines whether it is initialization or not def setIdValues(self, init): if init == 1: if TokList.getIdValue(self.id.name) == 'null': print('ERROR: value ' + self.id.name + ' is already initialized') exit() #Initialized to 'null' as None is the previous assignment, 'null' is used later to check for initialization TokList.setIdValue(self.id.name, 'null') if self.id_list is not None: self.id_list.setIdValues(1) else: self.id.setValue(TokList.currentData()) TokList.nextData() if self.id_list is not None: self.id_list.setIdValues(0)
class Case: def __init__(self): self.case_line = None self.expr = None self.id = None #Simple parse of the case statement def parse(self): TokList.match('CASE','case') self.id = Id() self.id.parse(TokList.getIdOrConst()) TokList.nextToken() TokList.match('OF','case') self.case_line = CaseLine() self.case_line.parse() TokList.match('ELSE','case') self.expr = Expr() self.expr.parse() TokList.match('END','case') TokList.match('SEMICOLON','case') #Printing with proper indentation manipulation and new line printings def print(self): TokList.printIndent() print('case ', end='') self.id.print() print(' of') TokList.increaseIndent() TokList.printIndent() self.case_line.print() #Necessary for new line printings print() TokList.printIndent() print('else ', end='') self.expr.print() print() TokList.decreaseIndent() TokList.printIndent() print('end;') #Recursive execution based on values in the case line. Id value is passed in to all versions of case def exec(self): if not (self.case_line.exec(self.id)): self.id.setValue(self.expr.exec())
class Factor: def __init__(self): self.const = None self.id = None self.expr = None #Simple parsing that checks for constant, Id, or paranthesis def parse(self): if TokList.checkTok('CONST'): self.const = Const() self.const.parse(TokList.getIdOrConst()) TokList.nextToken() elif TokList.checkTok('ID'): self.id = Id() self.id.parse(TokList.getIdOrConst()) TokList.nextToken() elif TokList.match('LEFTPARAN', 'factor'): self.expr = Expr.Expr() self.expr.parse() TokList.match('RIGHTPARAN', 'factor') #Simple print statement def print(self): if self.const is not None: self.const.print() elif self.id is not None: self.id.print() elif self.expr is not None: print('(', end='') self.expr.print() print(')', end='') #Simple execution statement that returns a value based on parsing def exec(self): if self.const is not None: return self.const.exec() elif self.id is not None: return self.id.exec() elif self.expr is not None: return self.expr.exec()