def toFunContent(self, fun): lines = [] if len(fun.args) != len(self.callArgs): raise CompilationException( 'function “{}” takes exactly {} arguments, {} is receved line {}' .format(fun.name, fun.args, self.callArgs, self.line)) lines += setters(map(lambda a: fun.ids[a], fun.args), self.callArgs) lines.append( AsmInst('op', [ Value('add'), fun.returnAddress, Value('@counter'), Value('1') ])) lines.append( Jump('jump to function {}'.format(self.name), fun.refDefinition)) # function returned # set tmp to var return if len(self.returnTo): if len(self.returnTo) != len(fun.returns): raise CompilationException( 'function “{}” return exactly {} values, {} is receved line {}' .format(fun.name, len(fun.returns), len(self.returnTo), self.line)) lines += setters(self.returnTo, fun.returns) return lines
def invalideSubInstr(p, line=None, valideKeys=None, indexErr=2): valideKeys = valideKeys if valideKeys else subInstr[toStrToken(p[1])] if p[indexErr].type == 'EndLine': return CompilationException( getStartMsg(p, line=line, end=', ') + "require keyword, must be on of: {}".format(valideKeys)) return CompilationException( getStartMsg(p, line=line, end=', ') + "'{}' is not a valide keyword, must be on of: {}".format(toStrToken(p[indexErr]), valideKeys))
def staticList(p: YaccProduction): '''noLine : affectation list''' if len(p[1]) != 1: raise CompilationException( "afectation incorrect: {} is not accepted".format(p[1])) name = p[1][0] val = p[2] if name in context.staticVarsList: raise CompilationException( "static list named: ⸄{}⸅ alrealy defined".format(name)) context.staticVarsList[name] = val
def maybeNotEnoughtArgs(p, nbArgsReq, line=None): tokenErr = p[len(p) - 1] instrArgs = p[len(p) - 2] nbArgsGiven = len(instrArgs) if tokenErr.type in reserved: return reservedKeword(p, tokenErr, line=line) elif tokenErr.type == 'EndLine': return notEnoughtArgs(p, nbArgsReq, nbArgsGiven, line=line) elif tokenErr.type == 'OpenParenthesis': return CompilationException( getStartMsg(p, line) + "is a reserved keyword, it can't be use to function name" ) raise CompilationException(getStartMsg(p, line) + "error found")
def radarMaybeNotEnought3(p: YaccProduction): '''ligne : radar error | uradar error''' tokenErr = p[len(p) - 1] startMsg = err.getStartMsg(p) if tokenErr.type != 'EndLine': raise CompilationException( startMsg + "the first three arguments of this instruction must be one of: {}". format(keywords.radarTarget) + ", '{}' given instead".format(tokenErr.value)) raise CompilationException( startMsg + "not enought arguments, the first three arguments of this instruction must be one of: {}" .format(keywords.radarTarget))
def radarMaybeNotEnought(p: YaccProduction): '''ligne : radar radarTarget radarTarget radarTarget radarSort error | uradar radarTarget radarTarget radarTarget radarSort error''' tokenErr = p[len(p) - 1] startMsg = err.getStartMsg(p) if tokenErr.type == 'EndLine': raise CompilationException(startMsg + "not enought arguments") raise err.reservedKeword(p, tokenErr)
def grammar(p_fun: Callable): p_name = p_fun.__name__ if p_name in context.p_fun: raise CompilationException( "function {} is defined more than once".format(p_name)) context.p_fun[p_name] = p_fun p_import = p_fun.__module__ if p_import not in context.p_imports: context.p_imports[p_import] = True return p_fun
def getFunCalled(self, moduleName, name, lineCall): module = self.getModule(moduleName) if name not in module: raise CompilationException( "function '{}' does not exist, module {}, at line {}".format( name, moduleName, lineCall)) fun = module[name] if not fun.defined: self.linesFunDef += fun.generateDefinition(moduleName) return fun
def mustBeVar(p, index, line=None): error = p[index] strErr = toStrToken(error) endMsg = "'{}' not valide".format(strErr) if error.type in reserved: endMsg = "'{}' is a reserved keyword".format(strErr) if error.type == 'EndLine': endMsg = "no variable given" return CompilationException( getStartMsg(p, line) + "require a variable to store result at position {}, {}" .format(index, endMsg))
def defFun(p: YaccProduction): '''noLine : dottedID OpenParenthesis arguments CloseParenthesis OpenCurlyBracket funDefContext lines CloseCurlyBracket''' # noqa if len(p[1]) != 1: raise CompilationException( "line {}, function definition incorrect: {} is not accepted" .format(p.lineno(2), p[1])) name = p[1][0] args = p[3] content = p[7] fundef = FunDef(context, name, args, content) importsHandling.imports.addFunToModule(fundef) context.inFunDefinition = False
def radarMaybeNotEnought2(p: YaccProduction): '''ligne : radar radarTarget radarTarget radarTarget error | uradar radarTarget radarTarget radarTarget error''' tokenErr = p[len(p) - 1] startMsg = err.getStartMsg(p) endmsg = 'only 3 arguments provided' if tokenErr.type != 'EndLine': endmsg = "'{}' given instead".format(tokenErr.value) raise CompilationException( startMsg + "the 4th argument of this instruction must be one of: {}, ".format( keywords.radarSort) + endmsg)
def generateDefinition(self, moduleName): if self.defined: raise CompilationException("function {} is already defined".format( self.name)) self.defined = True self.refDefinition = self.context.genRef() self.returnAddress = self.getReturnAddr(moduleName) lines = [self.refDefinition] + self.content if self.returnRef: lines.append(self.returnRef) # jump to funCall lines.append(AsmInst('set', [Value('@counter'), self.returnAddress])) return lines
def handleIndent(t: LexToken): nb = len(t.value[1:]) if nb / endLineContext.indentNb != nb // endLineContext.indentNb: raise CompilationException('line {}, indentation incorrect to previous lines in file'.format(t.lineno)) indentLvl = len(t.value[1:]) // endLineContext.indentNb if indentLvl > endLineContext.previousIndentationLvl: return indentUp(t, indentLvl) elif indentLvl < endLineContext.previousIndentationLvl: return indentDown(t, indentLvl) endLineContext.previousIndentationLvl = indentLvl return t
def staticFor(p: YaccProduction): '''lines : For arguments ID liNameOrList OpenCurlyBracket lines CloseCurlyBracket''' decompose = p[2] li = p[4] originalLines = p[6] refDict = {} # create list of ref for line in originalLines: if isinstance(line, Ref): refDict[line] = None for el in li: if len(decompose) != len(el): raise CompilationException( "cannot unpack list, el length not equal") # do a variable replacing lines = [] for tuple in li: copiedLines = [el.copy() for el in originalLines] for k in refDict.keys(): # new refs refDict[k] = context.genRef() for line in copiedLines: if isinstance(line, Ref): # change ref line.changeRef(refDict[line]) elif isinstance(line, Jump): if line.ref in refDict: line.changeRef(refDict[line.ref]) for toReplace, toReplaceBy in zip(decompose, tuple): line.replace(toReplace, toReplaceBy) else: for toReplace, toReplaceBy in zip(decompose, tuple): line.replace(toReplace, toReplaceBy) lines += copiedLines p[0] = lines
def __init__(self, variable: str) -> None: if not isinstance(variable, str): raise CompilationException( "Variable construction, input is not a string !") self.variable = variable
def error(t: LexToken): print("Syntax error in input!") return if t is not None: raise CompilationException("at line: {}, wasn't expecting: {}".format(t.lineno, t.type)) raise CompilationException("end of line reached")
def handleReturn(p: YaccProduction): '''ligne : Return arguments''' if not context.inFunDefinition: raise CompilationException( "line {}, return statement must be in function definition".format(p.lineno(1))) p[0] = ReturnStm(p[2])
def tooManyArgsNameIt(p, tokenErr, line=None): return CompilationException( getStartMsg(p, line) + "too many arguments, '{}' is exeeding".format(tokenErr.value) )
def tooManyArgs(p, nbArgsReq, nbArgsGiven, line=None): return CompilationException( getStartMsg(p, line) + "require {} arguments, {} given".format(nbArgsReq, nbArgsGiven) )
def reservedKeword(p, tokenErr, line=None): return CompilationException( getStartMsg(p, line=line, end=', ') + "'{}' is a reserved keyword, it could not be used as variable".format(toStrToken(tokenErr)))
def refToLine(self, refDict): if self.ref.id not in refDict: raise CompilationException( "for jump at line: {}, ref {} does not exist".format( self.line, self.ref.id)) self.refLine = refDict[self.ref.id]
def __init__(self, ref: str) -> None: if not isinstance(ref, str): if not isinstance(ref, int): raise CompilationException("error") self.id = ref
def invalideInstr(p, line=None): return CompilationException( getStartMsg(p, line) + "is not valide, valides instuctions are: {}".format(instr) )
def addRef(self, ref, index): if ref.id in self.refDict: raise CompilationException('ref {} already declared'.format( ref.id)) self.refDict[ref.id] = index
def getModule(self, fileLib): if fileLib not in self.imported: raise CompilationException( "module {} is used but not imported".format(fileLib)) return self.imported[fileLib]
def addFunToModule(self, funDef): if funDef.name in self.imported[self.currentFile]: raise CompilationException("function {} already defined".format( funDef.name)) self.imported[self.currentFile][funDef.name] = funDef
def indentUp(t: LexToken, indentLvl): if indentLvl > endLineContext.previousIndentationLvl + 1: raise CompilationException('too much indentation line {}'.format(t.lineno)) t.type = 'OpenCurlyBracket' endLineContext.previousIndentationLvl = indentLvl return t
def t_error(t: LexToken): if t.value[0] == ' ': t.lexer.skip(1) else: raise CompilationException("Illegal character '{}', line: {}".format(t.value[0], t.lineno))
def radarTooManyArgs(p: YaccProduction): '''ligne : radar radarTarget radarTarget radarTarget radarSort info info variable error | uradar radarTarget radarTarget radarTarget radarSort info info variable error''' raise CompilationException(err.getStartMsg(p) + "too many arguments")