def __init__(self, source, target, graph, edgeType="", basicAttrs=None): """ Create a new edge instance. Usually this constructor shall not be used directly @param source A node instance @param target The node instance that acts as the target node @param graph The graph this edge belongs to @param The edge type @param basicAttrs The basic attributes, or None to use empty set. """ #Ensure we have valid ID strings if isinstance(source, str): Identifier.checkIdentifier(source) elif isinstance(source, Node): target = source.id if isinstance(target, str): Identifier.checkIdentifier(target) elif isinstance(source, Node): source = target.id self.source = source self.target = target self.graph = graph self.type = edgeType #Serialize the edge database keys self.activeKey = "%s\x1F%s\x0E%s" % (edgeType, self.source, self.target) self.passiveKey = "%s\x1F%s\x0F%s" % (edgeType, self.target, self.source) #Initialize basic and extended attributes self.initializeAttributes(basicAttrs)
def main(cls, args): """ generated source for method main """ if len(args) == 1: print("Uso: IdentifierMain <string>") else: id = Identifier() if id.validateIdentifier(args[1]): print("Valido") else: print("Invalido")
def start(update, context): IDF = Identifier(Tokens=["DOGE-USD"]) while (True): identifier = IDF.update() for token in identifier: if identifier[token] > 3: context.bot.send_message(chat_id=update.effective_chat.id, text="{} is striking {} downs".format( token, identifier["DOGE-USD"])) time.sleep(60)
def __init__(self, tokens, outputFilePath, debugFlag): # Variables assigned from arguments self.tokenStream = deque(tokens) self.tokensForLookBack = deque(tokens) self.outputFilePath = outputFilePath # Check whether to print out each token as it's parsed if debugFlag == "0": self.debugMode = False else: self.debugMode = True # Variables relating to parsing tokens self.callingFunctionIsLet = False self.currentToken = "" self.symbolTable = SymbolTable.SymbolTable() self.identifier = Identifier(self.symbolTable) self.classVarDec = ["static", "field"] self.subroutineDec = ["constructor", "function", "method"] self.statements = ["let", "if", "else", "while", "do", "return"] self.callStatement = { "let" : self.compileLet, "if" : self.compileIf, "else" : self.compileWhile, "while" : self.compileWhile, "do" : self.compileDo, "return" : self.compileReturn } # Variables that hold the current xml element for a often used element self.doElement = None self.classVarDecElement = None self.elseElement = None self.expressionElement = None self.expressionElements = [] self.ifElement = None self.letElement = None self.parameterListDecElement = None self.parentElement = None self.parentOfParentElement = None self.parentStatementsToIfOrWhile = None self.returnElement = None self.subroutineBodyElement = None self.subroutineDecElement = None self.statementsElement = None self.varDecElement = None self.whileElement = None # XML structure root self.root = ET.Element("class") # Used to keep track of values that are accessed in differently scoped functions self.current = Current() # Variables for turning xml structure into VM code self.VMWriter = VMWriter.VMWriter(outputFilePath)
def parseCommand(): if (Parser.tokens.actual.token_type == "PTVIRGULA"): node = NoOp() Parser.tokens.selectNext() return node elif (Parser.tokens.actual.token_type == "DATA_TYPE"): identifier = Identifier() identifier.tipo = Parser.tokens.actual.value Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "NOME"): identifier.value = Parser.tokens.actual.value Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "EQUAL"): node = Assignment(Parser.tokens.actual.value) Parser.tokens.selectNext() node.children.append(identifier) node.children.append(Parser.parseRelexpr()) if (Parser.tokens.actual.token_type == "PTVIRGULA"): Parser.tokens.selectNext() return node else: raise ValueError('Esperado um ponto e virgula') else: raise ValueError('Esperado um assignment') elif (Parser.tokens.actual.token_type == "LOG"): node = Echo(Parser.tokens.actual.value) Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "APAR"): Parser.tokens.selectNext() node.children.append(Parser.parseRelexpr()) if (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "PTVIRGULA"): Parser.tokens.selectNext() return node else: raise ValueError('Esperado um ponto e virgula') else: raise ValueError('Esperado um parentesis') else: raise ValueError('Esperado um parentesis') elif (Parser.tokens.actual.token_type == "IF"): node = If(Parser.tokens.actual.value) Parser.tokens.selectNext() node.children.append(Parser.parseRelexpr()) # if(Parser.tokens.actual.token_type == "INTERR"): # Parser.tokens.selectNext() node.children.append(Parser.parseCommand()) # if(Parser.tokens.actual.token_type == "DOISP"): # Parser.tokens.selectNext() node.children.append(Parser.parseCommand()) return node # else: # return node # else: # raise ValueError('Esperado um parenteses') elif (Parser.tokens.actual.token_type == "WHILE"): node = While(Parser.tokens.actual.value) Parser.tokens.selectNext() node.children.append(Parser.parseRelexpr()) node.children.append(Parser.parseCommand()) return node elif (Parser.tokens.actual.token_type == "FUNCTION"): Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "NOME"): node = FuncDec(Parser.tokens.actual.value) Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "EQUAL"): Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "DATA_TYPE"): node.return_type = Parser.tokens.actual.value Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "APAR"): Parser.tokens.selectNext() while (True): if (Parser.tokens.actual.token_type == "DATA_TYPE"): identifier = Identifier() identifier.tipo = Parser.tokens.actual.value Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "NOME"): identifier.value = Parser.tokens.actual.value Parser.tokens.selectNext() node.children.append(identifier) if (Parser.tokens.actual.token_type == "VIRGULA"): Parser.tokens.selectNext() elif (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() node.children.append( Parser.parseBlock()) return node else: raise ValueError( "Esperado uma virgula ou parentesis" ) elif (Parser.tokens.actual.token_type == "FPAR" ): Parser.tokens.selectNext() node.children.append(Parser.parseBlock()) return node else: raise ValueError("Esperado um identifier") else: raise ValueError("Esperado um parentesis") else: raise ValueError( "Esperado o tipo do retorno da funcao") else: raise ValueError("Esperado o nome da funcao") elif (Parser.tokens.actual.token_type == "RETURN"): node = Return(Parser.tokens.actual.token_type) Parser.tokens.selectNext() node.children.append(Parser.parseRelexpr()) if (Parser.tokens.actual.token_type == "PTVIRGULA"): Parser.tokens.selectNext() return node else: raise ValueError('Esperado um ponto e virgula') elif (Parser.tokens.actual.token_type == "NOME"): node = FuncCall(Parser.tokens.actual.value) Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "APAR"): Parser.tokens.selectNext() while (True): if (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() return node else: node.children.append(Parser.parseRelexpr()) if (Parser.tokens.actual.token_type == "VIRGULA"): Parser.tokens.selectNext() elif (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() return node else: raise ValueError( "Esperado uma virgula ou parentesis") else: raise ValueError("Esperado um parentesis") else: return Parser.parseBlock()
def parseFactor(): if (Parser.tokens.actual.token_type == "INT"): node = IntVal(Parser.tokens.actual.value) Parser.tokens.selectNext() return node if (Parser.tokens.actual.token_type == "FLOAT"): node = FloatVal(Parser.tokens.actual.value) Parser.tokens.selectNext() return node elif (Parser.tokens.actual.token_type == "BOOL"): node = BoolVal(Parser.tokens.actual.value) Parser.tokens.selectNext() return node elif (Parser.tokens.actual.token_type == "STRING"): node = StringVal(Parser.tokens.actual.value) Parser.tokens.selectNext() return node elif (Parser.tokens.actual.token_type == "IDENTIFIER"): identifier = Identifier() identifier.value = Parser.tokens.actual.value Parser.tokens.selectNext() return identifier elif ((Parser.tokens.actual.token_type == "PLUS") or (Parser.tokens.actual.token_type == "MINUS")): if (Parser.tokens.actual.token_type == "PLUS"): node = UnOp(Parser.tokens.actual.value) Parser.tokens.selectNext() res_factor = Parser.parseFactor() node.children.append(res_factor) elif (Parser.tokens.actual.token_type == "MINUS"): node = UnOp(Parser.tokens.actual.value) Parser.tokens.selectNext() res_factor = Parser.parseFactor() node.children.append(res_factor) elif (Parser.tokens.actual.token_type == "NOT"): node = UnOp(Parser.tokens.actual.value) Parser.tokens.selectNext() res_factor = Parser.parseFactor() node.children.append(res_factor) elif (Parser.tokens.actual.token_type == "APAR"): Parser.tokens.selectNext() res = Parser.parseRelexpr() if (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() return res else: raise ValueError('Parenteses nao foi fechado') elif (Parser.tokens.actual.token_type == "READLINE"): node = Readline(Parser.tokens.actual.value) Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "APAR"): Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() return node else: raise ValueError('Parenteses nao foi fechado') else: raise ValueError('Parenteses nao foi aberto') elif (Parser.tokens.actual.token_type == "NOME"): value = Parser.tokens.actual.value Parser.tokens.selectNext() if (Parser.tokens.actual.token_type == "APAR"): node = FuncCall(value) Parser.tokens.selectNext() while (True): node.children.append(Parser.parseRelexpr()) if (Parser.tokens.actual.token_type == "VIRGULA"): Parser.tokens.selectNext() elif (Parser.tokens.actual.token_type == "FPAR"): Parser.tokens.selectNext() return node else: raise ValueError("Esperado uma virgula ou parentesis") else: identifier = Identifier() identifier.value = value return identifier else: raise ValueError('Erro') return node
class JackEngine(): def __init__(self, tokens, outputFilePath, debugFlag): # Variables assigned from arguments self.tokenStream = deque(tokens) self.tokensForLookBack = deque(tokens) self.outputFilePath = outputFilePath # Check whether to print out each token as it's parsed if debugFlag == "0": self.debugMode = False else: self.debugMode = True # Variables relating to parsing tokens self.callingFunctionIsLet = False self.currentToken = "" self.symbolTable = SymbolTable.SymbolTable() self.identifier = Identifier(self.symbolTable) self.classVarDec = ["static", "field"] self.subroutineDec = ["constructor", "function", "method"] self.statements = ["let", "if", "else", "while", "do", "return"] self.callStatement = { "let" : self.compileLet, "if" : self.compileIf, "else" : self.compileWhile, "while" : self.compileWhile, "do" : self.compileDo, "return" : self.compileReturn } # Variables that hold the current xml element for a often used element self.doElement = None self.classVarDecElement = None self.elseElement = None self.expressionElement = None self.expressionElements = [] self.ifElement = None self.letElement = None self.parameterListDecElement = None self.parentElement = None self.parentOfParentElement = None self.parentStatementsToIfOrWhile = None self.returnElement = None self.subroutineBodyElement = None self.subroutineDecElement = None self.statementsElement = None self.varDecElement = None self.whileElement = None # XML structure root self.root = ET.Element("class") # Used to keep track of values that are accessed in differently scoped functions self.current = Current() # Variables for turning xml structure into VM code self.VMWriter = VMWriter.VMWriter(outputFilePath) def advanceToken(self): if self.tokenStream: self.currentToken = self.tokenStream.popleft() if self.debugMode: self.debug("currentToken: ") return else: print "hit last token" def addCurrentTokenAsChildElement(self, parentElement): childTokenElement, childTokenValue = self.currentToken.items()[0] child = ET.SubElement(parentElement, childTokenElement) child.text = childTokenValue if childTokenElement == IDENTIFIER: self.compileIdentifier(child, parentElement) return def compileIdentifier(self, child, parent): # Determine if identifier is being declared or used self.identifier.identify(child, parent) beingDefined = child.get("beingDefined") identifierCategory = child.get("category") # print child.text + SPACE + beingDefined if beingDefined == "yes": self.addIdentifierToSymbolTable(child, identifierCategory) self.getIdentifierFromSymbolTable(child) else: self.compileIdentifierUse(child, parent, identifierCategory) return def compileIdentifierUse(self, child, parent, identifierCategory): if identifierCategory == SymbolTable.CLASS: return # If identifier is part of a do statement, it's a subroutine name elif parent.tag == "doStatement": self.identifier.setAttribute(child, "category", "subroutine") # If an identifier is part of a let statement, it can be a subroutine or a variable elif parent.tag == "letStatement": # If it's a variable, then it will be declared already, so try to find it kind = self.symbolTable.kindOf(child.text) # Check the class, too if kind == None: self.setClassAsCurrentScope() kind = self.symbolTable.kindOf(child.text) self.setMethodAsCurrentScope() if kind == None: self.identifier.setAttribute(child, "category", "subroutine") else: self.getIdentifierFromSymbolTable(child) else: self.getIdentifierFromSymbolTable(child) # Else, it's a subroutine else: self.getIdentifierFromSymbolTable(child) return def addIdentifierToSymbolTable(self, child, identifierCategory): # Then add identifier to symbol table if identifierCategory == SymbolTable.CLASS: self.symbolTable.startClass(child.text) elif identifierCategory == SymbolTable.SUB_ROUT_DEC: #print self.currentTokenValue() self.symbolTable.startSubroutine() elif identifierCategory in SymbolTable.VARS: self.symbolTable.define(child.text, child.get("type"), child.get("category")) return def getIdentifierFromSymbolTable(self, child): ''' :param child: xml element (of identifier) :return: void Appends attributes the xml element representing the identifier by looking up the identifier in the symbol table ''' attributes = self.identifier.getAttributes(child.text) self.identifier.setAttributes(child, attributes) return def isLastToken(self): if len(self.tokenStream) >= 1: return False return True def setClassAsCurrentScope(self): self.symbolTable.currentScopeIndex = self.symbolTable.classScopeIndex def setMethodAsCurrentScope(self): self.symbolTable.currentScopeIndex = self.symbolTable.methodScopeIndex def compile(self): self.compileClass() # Return parsed XML tree self.indentXML() #return self.root return def compileClass(self): ''' Compiles a complete class ''' self.advanceToken() if self.currentTokenValue() in self.classVarDec: # Current token is the first element of the new sub-element self.classVarDecElement = ET.SubElement(self.root, "classVarDec") self.addCurrentTokenAsChildElement(parentElement = self.classVarDecElement) self.compileClassVarDec() self.compileClass() elif self.currentTokenValue() in self.subroutineDec: # Current token is the first element of the new sub-element self.subroutineDecElement = ET.SubElement(self.root, "subroutineDec") self.addCurrentTokenAsChildElement(parentElement = self.subroutineDecElement) self.compileSubroutine() self.compileClass() # We're done elif self.currentTokenValue() == RIGHT_BRACE: self.addCurrentTokenAsChildElement(parentElement = self.root) return else: self.addCurrentTokenAsChildElement(parentElement = self.root) self.compileClass() def compileClassVarDec(self): ''' Compiles a static declaration or a field declaration ''' self.advanceToken() while self.currentTokenValue() is not SEMI_COLON: self.addCurrentTokenAsChildElement(parentElement = self.classVarDecElement) if self.currentTokenKey() == IDENTIFIER: self.current.numClassVars += 1 self.advanceToken() return def compileSubroutine(self): ''' Compiles a complete method, function, or constructor. Starts on function owner ''' self.current.subroutineType = self.currentTokenValue() # constructor, function or method # Append type self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = self.subroutineDecElement) # Append name self.advanceToken() self.current.subroutineName = self.currentTokenValue() self.addCurrentTokenAsChildElement(parentElement = self.subroutineDecElement) # If it's a method call, this is argument 0 if self.current.subroutineType == METHOD: self.symbolTable.kindCounter["arg"] += 1 # Append param list symbol self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = self.subroutineDecElement) # Compile the parameter list self.parameterListDecElement = ET.SubElement(self.subroutineDecElement, "parameterList") self.compileParameterList() # Append closing param list symbol self.addCurrentTokenAsChildElement(parentElement = self.subroutineDecElement) self.subroutineBodyElement = ET.SubElement(self.subroutineDecElement, "subroutineBody") self.compileSubroutineBody() # Reset if/while statement count self.VMWriter.resetStatementCount() return def compileParameterList(self): ''' Compiles a (possibly empty) parameter list ''' self.advanceToken() # If the parameter list is empty or we're done compiling it if self.currentTokenValue() == RIGHT_PARENTHESIS: return # Else self.addCurrentTokenAsChildElement(parentElement = self.parameterListDecElement) self.compileParameterList() return def compileSubroutineBody(self): ''' Compiles either a varDec or statements ''' self.advanceToken() # If beginning of body if self.currentTokenValue() == LEFT_BRACE: self.addCurrentTokenAsChildElement(parentElement = self.subroutineBodyElement) self.compileSubroutineBody() # If end of body elif self.currentTokenValue() == RIGHT_BRACE or self.currentTokenValue() == RIGHT_BRACE_WITH_SPACE: self.addCurrentTokenAsChildElement(parentElement = self.subroutineBodyElement) # Return to compile SR, which will return to compile class. return # If var dec elif self.currentTokenValue() == "var": self.varDecElement = ET.SubElement(self.subroutineBodyElement, "varDec") self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) self.compileVarDec() self.compileSubroutineBody() # If statement elif self.currentTokenValue() in self.statements: # Because we're into the subroutine's statements, all vars have been declared, so write subroutine dec self.VMWriter.writeFunction(name = self.current.subroutineName, nLocals = self.current.numLocals) # If we are constructing an object, we need to allocate space for it if self.current.subroutineType == CONSTRUCTOR: self.VMWriter.writePush(CONST, self.current.numClassVars) self.VMWriter.writeCall("Memory.alloc", 1) # Take the value returned from alloc and put it in "this" self.VMWriter.writePop(POINTER, 0) if self.current.subroutineType == METHOD: # Set the value of this self.VMWriter.writePush(ARG, 0) self.VMWriter.writePop(POINTER, 0) # Reset the subroutine dec info self.current.numClassVars = 0 self.current.numLocals = 0 self.current.subroutineName = "" self.current.subroutineType = "" self.statementsElement = ET.SubElement(self.subroutineBodyElement, "statements") self.parentElement = self.subroutineBodyElement self.compileStatements() self.addCurrentTokenAsChildElement(parentElement = self.subroutineBodyElement) # Return to subroutine dec return else: return def compileVarDec(self): ''' Compiles a var declaration ''' # Advance past var keyword self.advanceToken() # Compile type self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) self.advanceToken() # Compile name self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) self.current.numLocals += 1 self.advanceToken() while self.currentTokenValue() == COMMA: # Compile the comma self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) self.advanceToken() # Compile the name self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) # Increment num locals for this subroutine self.current.numLocals += 1 self.advanceToken() # Append the closing semi-colon self.addCurrentTokenAsChildElement(parentElement = self.varDecElement) return def compileStatements(self, parentStatement = None): ''' Compiles a sequence of statements, not including the enclosing {} ''' # If no more statements if self.currentTokenValue() == RIGHT_BRACE or self.currentTokenValue() == RIGHT_BRACE_WITH_SPACE: return else: # Call statement self.callStatement[self.currentTokenValue()]() self.compileStatements() def resetDoElements(self): self.current.numExpressions = 0 self.current.subroutineName = "" def isVar(self, tokenValue): ''' :return: bool Returns whether the current token is a method. Determined by checking if current token is a variable. In the context of a do statement (which calls this func), a variable beginning the do statement means the subR call is a method call ''' if self.symbolTable.kindOf(tokenValue) == None: return False return True def compileDo(self): ''' Compiles a do statement: -- do subroutineCall -- ''' # Initially set to false, reset to false at end methodCall = False self.current.numExpressions = 0 # Compile do keyword (do) self.doElement = ET.SubElement(self.statementsElement, "doStatement") self.addCurrentTokenAsChildElement(parentElement = self.doElement) self.advanceToken() # 3 cases: (1) do method() (2) do var.method() (3) do class.function() tokenIsVar = self.isVar(self.currentTokenValue()) # Case: do var.method() if tokenIsVar: # Subroutine to call will be the varType, not it's name (because it's a method) varName = self.currentTokenValue() varAttributes = self.identifier.getAttributes(varName) self.current.subroutineName = varAttributes["type"] # Append dot and subR name to var name self.advanceToken() while self.currentTokenValue() is not LEFT_PARENTHESIS: self.addCurrentTokenAsChildElement(parentElement = self.doElement) self.current.subroutineName = self.current.subroutineName + self.currentTokenValue() self.advanceToken() else: tokenValue = self.currentTokenValue() self.advanceToken() # Case: do method() if self.currentTokenValue() == LEFT_PARENTHESIS: self.addCurrentTokenAsChildElement(parentElement = self.doElement) self.current.subroutineName = self.VMWriter.className + DOT + tokenValue methodCall = True # Don't advance token, so that compiling the EL starts on left paren # Case: do class.function() else: self.current.subroutineName = tokenValue while self.currentTokenValue() is not LEFT_PARENTHESIS: self.addCurrentTokenAsChildElement(parentElement = self.doElement) self.current.subroutineName = self.current.subroutineName + self.currentTokenValue() self.advanceToken() # Compile the expression list: (expression,*) self.addCurrentTokenAsChildElement(parentElement = self.doElement) self.advanceToken() # Set do element as parent to the expression list self.parentElement = self.doElement if tokenIsVar: # Set the base self.VMWriter.writePush(varAttributes["kind"], varAttributes["index"]) # Method calls operate on k + 1 args self.current.numExpressions += 1 # Method calls operate on k + 1 args if methodCall: # Push value of this for function being called self.VMWriter.writePush(POINTER, 0) self.current.numExpressions += 1 # Save number of expressions compiled for VM code self.current.numExpressions = self.current.numExpressions + self.compileExpressionList() # Append closing paren to do element self.addCurrentTokenAsChildElement(parentElement = self.doElement) #print "closing paren: " + self.currentTokenValue() self.advanceToken() # Compile the semi-colon self.addCurrentTokenAsChildElement(parentElement = self.doElement) # Write the call self.VMWriter.writeCall(self.current.subroutineName, self.current.numExpressions) # Pop the return value self.VMWriter.writePop(TEMP, 0) # Advance to start of next non-terminal self.advanceToken() self.current.numExpressions = 0 return def compileLet(self): ''' Compiles a let statement ''' compilingArray = False # Compile let keyword self.letElement = ET.SubElement(self.statementsElement, "letStatement") self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # Compile varName for use later in function varName = self.currentTokenValue() kind = self.symbolTable.kindOf(varName) index = self.symbolTable.indexOf(varName) self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # Next token is either the beginning of an expression (index into an array) or an equal sign. # If expression, compile it and advance to the equal sign following it. if self.currentTokenValue() == BRACKET_EXPRESSION: compilingArray = True # Compile opening bracket self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # Compile expression self.parentElement = self.letElement self.compileExpression() # Push var onto the stack self.VMWriter.writePush(kind, index) # Add the result of the expression to the base of the variable self.VMWriter.writeArithmetic(ADD, BINARY) # Compile closing bracket self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # If nested brackets if self.currentTokenValue() == "]": self.advanceToken() # Compiled expression doesn't know about closing brace # Compile the equal sign and advance self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # Compile expression self.parentElement = self.letElement self.compileExpression() # Expression will be pushed to top of stack if compilingArray: # Pop the result of the expression into temp self.VMWriter.writePop(TEMP, 0) # Pop the address of the array into that self.VMWriter.writePop(POINTER, 1) # Push the expression result in temp onto the stack self.VMWriter.writePush(TEMP, 0) # Store the result in address that is pointing to self.VMWriter.writePop(THAT, 0) else: # Pop result of the expression into LHS of let statement self.VMWriter.writePop(kind, index) # Next token is either a semi-colon, right bracket or a right paren. # If right bracket or paren, we need an extra advance if self.currentTokenValue() in EXPRESSION_ENDER: self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() # Compile semi-colon and advance out of the let statement self.addCurrentTokenAsChildElement(parentElement = self.letElement) self.advanceToken() return def compileWhile(self): ''' Compiles a while statement ''' # Append while element self.whileElement = ET.SubElement(self.statementsElement, "whileStatement") # Determine what number while statement this is (in the current subroutine) self.VMWriter.statementCount[WHILE] += 1 parentWhileNumber = str(self.VMWriter.statementCount[WHILE]) # Save value of parent statement element and value of while element (for the case where a while statement has while statements as statements) parentWhile = self.whileElement parentToWhile = self.statementsElement # Append while keyword self.addCurrentTokenAsChildElement(parentElement = self.whileElement) self.VMWriter.writeLabel(WHILE, EXP, parentWhileNumber) # Advance and append the left paren that marks the beginning of an expression self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = self.whileElement) # Compile the expression, which will advance token(s) self.advanceToken() self.parentElement = self.whileElement self.compileExpression() # Not the result of the expression self.VMWriter.writeArithmetic(NOT, UNARY) # With the computed expression on the top of the stack, test if-goto self.VMWriter.writeIf(WHILE + "_" + END + parentWhileNumber) # Append the right paren that marks the end of the expression self.addCurrentTokenAsChildElement(parentElement = self.whileElement) # Advance to the left brace and append it self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = self.whileElement) # Advance to the first keyword of the first statement self.advanceToken() self.statementsElement = ET.SubElement(self.whileElement, "statements") self.compileStatements() # After writing statements, go to the beginning of while statement (and then test the expression again) self.VMWriter.writeGoto(WHILE + "_" + EXP + parentWhileNumber) # Add closing brace self.addCurrentTokenAsChildElement(parentElement = parentWhile) self.advanceToken() # Label denoting end of while statement self.VMWriter.writeLabel(WHILE, END, parentWhileNumber) # Reset the statement element self.statementsElement = parentToWhile return def compileReturn(self): ''' :return: Compile a return statement. Two cases: return; | return expression; ''' # Append return keyword self.returnElement = ET.SubElement(self.statementsElement, "returnStatement") self.addCurrentTokenAsChildElement(parentElement = self.returnElement) self.advanceToken() # Case: return; if self.currentTokenValue() == SEMI_COLON: self.addCurrentTokenAsChildElement(parentElement = self.returnElement) self.parentElement = self.returnElement self.advanceToken() self.VMWriter.writePush(CONST, 0) self.VMWriter.writeReturn() return # Case: return expression else: self.parentElement = self.returnElement self.compileExpression() # Append semi-colon and prepare for next statement (or end of statements) self.addCurrentTokenAsChildElement(parentElement = self.returnElement) self.advanceToken() self.VMWriter.writeReturn() return def compileIf(self): ''' Compiles an if statement, possibly with a trailing else clause ''' # Append if keyword self.ifElement = ET.SubElement(self.statementsElement, "ifStatement") # Determine what number if statement this is (in the current subroutine) self.VMWriter.statementCount[IF] += 1 parentIfCount = str(self.VMWriter.statementCount[IF]) # Save value of parent statement element and value of if element (for the case where a if statement has if statements as statements) parentIF = self.ifElement parentToIf = self.statementsElement self.addCurrentTokenAsChildElement(parentElement = self.ifElement) self.advanceToken() # Append paren as if symbol, then compile the expression self.addCurrentTokenAsChildElement(parentElement = self.ifElement) self.parentElement = self.ifElement self.advanceToken() self.compileExpression() # Not the result of the expression self.VMWriter.writeArithmetic(NOT, UNARY) # Determine which label to jump to self.VMWriter.writeIf(IF + "_" + FALSE + parentIfCount) self.VMWriter.writeGoto(IF + "_" + TRUE + parentIfCount) # Append closing paren self.addCurrentTokenAsChildElement(parentElement = self.ifElement) # Append opening brace as if symbol self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = self.ifElement) # Write TRUE label self.VMWriter.writeLabel(IF, TRUE, parentIfCount) # Compile statements after if expression self.advanceToken() self.statementsElement = ET.SubElement(self.ifElement, "statements") self.compileStatements() self.VMWriter.writeGoto(IF + "_" + END + parentIfCount) # If expression was true, statements executed. Now, jump to end of if statement #self.VMWriter.writeGoto(IF + "_" + FALSE + parentIfCount) self.statementsElement = parentToIf # Add closing brace to if self.addCurrentTokenAsChildElement(parentElement = parentIF) self.VMWriter.writeLabel(IF, FALSE, parentIfCount) # Check for a trailing else self.advanceToken() if self.currentTokenValue() == "else": self.addCurrentTokenAsChildElement(parentElement = parentIF) # Append the opening else brace to xml structure self.advanceToken() self.addCurrentTokenAsChildElement(parentElement = parentIF) # Compile statements in the else block self.advanceToken() self.compileStatements() # Append closing else brace self.addCurrentTokenAsChildElement(parentElement = parentIF) self.advanceToken() self.VMWriter.writeLabel(IF, END, parentIfCount) return def compileExpression(self): ''' Compiles an expression. ''' self.expressionElement = ET.SubElement(self.parentElement, "expression") self.parentElement = self.expressionElement # Compile the first term self.compileTerm() # Compile the op and second term while self.currentTokenValue() in OPS: operator = self.currentTokenValue() self.advanceToken() self.compileTerm() self.compileOp(operator) return def compileOp(self, operator): # XML tree child = ET.SubElement(self.parentElement, "symbol") child.text = operator self.VMWriter.writeArithmetic(operator, BINARY) return def compileTerm(self): ''' Compiles a term. This routine is faced with slight difficulty when trying to decide between alternate parsing roles If current token is an identifier, the routine must distinguish between a variable, an array entry, and a subroutine call. A single look ahead token, may may be one of "[", "(" or "." suffices to distinguish between the three possibilities Any other token is not part of this term and should not be advanced over. ''' self.termElement = ET.SubElement(self.parentElement, "term") self.parentElement = self.termElement # If term is a unary op if self.currentTokenValue() in UNARY_OPS: # Add unary op to tree self.addCurrentTokenAsChildElement(self.parentElement) operator = self.currentTokenValue() # Compile the term the op applies to self.advanceToken() self.compileTerm() # Write vm code self.VMWriter.writeArithmetic(operator, UNARY) return # If term is an expression elif self.currentTokenValue() == LEFT_PARENTHESIS: # Opening paren goes to term self.addCurrentTokenAsChildElement(parentElement = self.termElement) # Save hierarchy of the expression savedExpressionElement = self.expressionElement savedTermElement = self.termElement self.advanceToken() self.compileExpression() # Append closing paren to term self.addCurrentTokenAsChildElement(parentElement = savedTermElement) self.parentElement = savedExpressionElement self.advanceToken() return else: # Append to XML structure self.addCurrentTokenAsChildElement(parentElement = self.parentElement) # Process look ahead token if identifier if self.currentTokenKey() == IDENTIFIER: # Lookup identifier in symbolTable name = self.currentTokenValue() kind = self.symbolTable.kindOf(name) index = self.symbolTable.indexOf(name) # Look ahead to determine if identifier is beginning of an expression self.advanceToken() # If subroutine call with a class if self.currentTokenValue() == DOT: subroutineArgs = 0 subroutineName = name # Check if subroutine call is from a var tokenIsVar = self.isVar(name) if tokenIsVar: # Subroutine name is var's class type varAttributes = self.identifier.getAttributes(name) subroutineName = varAttributes["type"] # Push var as arg 0 self.VMWriter.writePush(varAttributes["kind"], varAttributes["index"]) subroutineArgs =+ 1 # Add dot and advance subroutineName = subroutineName + DOT self.addCurrentTokenAsChildElement(parentElement = self.parentElement) self.advanceToken() # Add subroutine name and advance subroutineName = subroutineName + self.currentTokenValue() self.addCurrentTokenAsChildElement(parentElement = self.parentElement) self.advanceToken() # Add opening paren and advance self.addCurrentTokenAsChildElement(self.termElement) self.advanceToken() savedTermElement = self.termElement self.parentElement = self.termElement # Compile expression list, returning number of expressions compiled (which equals num of args passed in) subroutineArgs = subroutineArgs + self.compileExpressionList() self.addCurrentTokenAsChildElement(parentElement = savedTermElement) # Write subroutine call self.VMWriter.writeCall(subroutineName, subroutineArgs) self.advanceToken() return # varName[expression] elif self.currentTokenValue() == BRACKET_EXPRESSION: savedTermElement = self.termElement self.addCurrentTokenAsChildElement(parentElement = self.termElement) self.parentElement = self.termElement # Advance to first term in expression and then compile the expression self.advanceToken() self.compileExpression() # Push varName self.VMWriter.writePush(kind, index) # Add the result of the expression to the base of the variable self.VMWriter.writeArithmetic(ADD, BINARY) # Pop sum into "that" pointer self.VMWriter.writePop(POINTER, 1) # Push value of address that is pointing to self.VMWriter.writePush("that", 0) # Append closing bracket self.addCurrentTokenAsChildElement(parentElement = savedTermElement) self.advanceToken() return # If a subroutine call elif self.currentTokenValue() == LEFT_PARENTHESIS: # Parens symbol goes with the term self.compileExpressionList() return # Else, look ahead token is not part of greater identifier, so compile it as separate term or op else: if self.currentTokenValue() == "]": self.VMWriter.writePush(kind, index) return else: # Push the token before the look ahead token self.VMWriter.writePush(segment=kind, index=index) self.parentElement = self.expressionElement return # If current token is not an identifier or op, then it's a keyword, constant (string or int) else: if self.currentTokenKey() == KEYWORD: keyword = self.currentTokenValue() self.VMWriter.writeKeywordConstant(keyword) self.advanceToken() elif self.currentTokenKey() == STRING: # Create new string string = self.currentTokenValue() stringLen = len(string) self.VMWriter.writePush(CONST, stringLen) self.VMWriter.writeCall("String.new", 1) # Append each character to string for char in string: self.VMWriter.writePush(CONST, ord(char)) self.VMWriter.writeCall("String.appendChar", 2) self.advanceToken() # Otherwise, it's an int else: self.VMWriter.writePush(CONST, self.currentTokenValue()) self.advanceToken() return def compileExpressionList(self): ''' Compiles a (possibly empty) comma-separated list of expressions ''' numExpressions = 0 self.expressionListElement = ET.SubElement(self.parentElement, "expressionList") self.parentElement = self.expressionListElement # Return if expression list is empty if self.currentTokenValue() == RIGHT_PARENTHESIS: return numExpressions else: numExpressions += 1 self.compileExpression() while self.currentTokenValue() == COMMA: numExpressions += 1 self.addCurrentTokenAsChildElement(parentElement = self.expressionListElement) self.advanceToken() # Reset expression list as the parent element self.parentElement = self.expressionListElement self.compileExpression() return numExpressions def currentTokenKey(self): return self.currentToken.keys()[0] def currentTokenValue(self): return self.currentToken.values()[0] def debug(self, optionalString=""): print optionalString + self.currentTokenValue() + " " + self.outputFilePath def indent(self, elem, level=0): i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: self.indent(elem, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i def indentXML(self): self.indent(self.root) return
def get_idea_rules(): literals = MappingRule(name="literals", mapping={ "cos": Text("\"") + Key("space"), "num": Text("%(n)d"), }, extras=[ IntegerRef("n", 1, 1000000), Dictation("text"), ]) capitalization = MappingRule(name="capitalization", mapping={ "var <identifier>": Identifier("%(identifier)s"), "camel <identifier>": CamelCase("%(identifier)s"), "speak <identifier>": Text("%(identifier)s"), }, extras=[ Dictation("identifier"), ]) class_rules = MappingRule( name="clas_rules", mapping={ "new": Text("new "), "pum [<identifier>]": Text("public void ") + Identifier("%(identifier)s() { \n"), "puma [<identifier>]": Text("public abstract void ") + Identifier("%(identifier)s() { \n"), "pum static [<identifier>]": Text("public static void ") + Identifier("%(identifier)s() { \n"), "pim [<identifier>]": Text("private void ") + Identifier("%(identifier)s() { \n"), "pima [<identifier>]": Text("private abstract void ") + Identifier("%(identifier)s() { \n"), "pim static [<identifier>]": Text("private void ") + Identifier("%(identifier)s() { \n"), "pom [<identifier>]": Text("protected void ") + Identifier("%(identifier)s() { \n"), "poma [<identifier>]": Text("protected abstract void ") + Identifier("%(identifier)s() { \n"), "pom static [<identifier>]": Text("protected static void ") + Identifier("%(identifier)s() { \n"), "pufu [<class_name>] [var <identifier>]": Text("public ") + CamelCase("%(class_name)s") + Text(" ") + Identifier("%(identifier)s() { \n"), "pifi [<class_name>] [var <identifier>]": Text("private ") + CamelCase("%(class_name)s") + Text(" ") + Identifier("%(identifier)s() { \n"), "pofo [<class_name>] [var <identifier>]": Text("protected ") + CamelCase("%(class_name)s") + Text(" ") + Identifier("%(identifier)s() { \n"), "test [<identifier>]": Key("c-n, enter") + Text("test"), "override": Key("c-n") + Key("down:6") + Key("enter"), "return": Text("return"), "static": Text("static"), "abstract": Text("abstract"), }, extras=[ Dictation("identifier"), Dictation("class_name"), ]) binary_operators = MappingRule(name="binary_operators", mapping={ "star": Key("asterisk"), "sum | plus": Key("plus"), "min": Key("minus"), "and": Text("&&"), "or": Text("||"), }, extras=[ Dictation("identifier"), ]) types = MappingRule(name="types", mapping={ "flag | bool | boolean": Text("boolean "), "long [<identifier>]": Text("long ") + Identifier("%(identifier)s"), "int [<identifier>]": Text("int ") + Identifier("%(identifier)s"), "double [<identifier>]": Text("double ") + Identifier("%(identifier)s"), "float [<identifier>]": Text("float ") + Identifier("%(identifier)s"), "string [<identifier>]": Text("String ") + Identifier("%(identifier)s"), "Integer [<identifier>]": Text("Integer ") + Identifier("%(identifier)s"), "class float [<identifier>]": Text("float ") + Identifier("%(identifier)s"), "class double [<identifier>]": Text("double ") + Identifier("%(identifier)s"), "list": Text("List<"), "collection | col": Text("Collection<"), "hash": Text("HashMap<"), "set": Text("HashSet<"), }, extras=[ Dictation("identifier"), ]) editing_chars = MappingRule(name="editing_chars", mapping={ "slap": Key("enter"), "tab": Key("tab"), "pa": Key("space"), }, extras=[ Dictation("text"), ]) symbols = MappingRule(name="symbols", mapping={ "this": Text("this"), "shasha": Text("//"), "cha": Text("/"), "comments [<text>]": Text("/**") + Key("enter") + Text("%(text)s \n"), "doh | dot": Key("dot"), "del": Key("del"), "se | semicolon": Text(";"), "koh | colon": Key("colon"), "ma": Key("comma"), "rak": Text("{"), "kar": Text("}"), "opa": Text("("), "apo": Text(")"), "brak": Text("["), "krak": Text("]"), }, extras=[ Dictation("text"), ]) ide_basic_commands = MappingRule(name="ide_basic", mapping={ "what | mimi": Key("c-space"), "reformat": Key("a-f8") + Key("enter"), "make class [<text>]": Key("a-f") + Key("a-insert") + Key("enter") + CamelCase("%(text)s"), "rename": Key("s-f6"), }, extras=[ Dictation("text"), ]) return [ binary_operators, types, symbols, ide_basic_commands, editing_chars, capitalization, class_rules, literals ]
def test_parse(self): """ Smoke test for the execute method """ iden = Identifier("%(identifier)s ") iden.execute({"identifier": "transformation count"})