def __parse(self, tokens): """ The recursive parser that builds the parse tree from one line of source code. :param tokens: The tokens from the source line separated by whitespace in a list of strings. :exception: raises a syntax_error.SyntaxError with the message 'Incomplete statement' if the statement is incomplete (e.g. there are no tokens left and this method was called). :exception: raises a syntax_error.SyntaxError with the message 'Invalid token {token}' if an unrecognized token is encountered (e.g. not one of the tokens listed above). :return: """ #self, variable, expression, symTbl, token if len(tokens) > 0: token = tokens.pop(0) else: return #raise syntax_error.SyntaxError('Incomplete statement') if token == self.COMMENT_TOKEN: return None elif token in self.PRINT_TOKEN: if len(tokens) > 0: return print_node.PrintNode(self.__parse(tokens)) else: return print_node.PrintNode(None) elif token in self.MATH_TOKENS: leftChild = self.__parse(tokens) rightChild = self.__parse(tokens) if not isinstance(leftChild, (literal_node.LiteralNode, math_node.MathNode, variable_node.VariableNode)): raise syntax_error.SyntaxError('Invalid Statement') if not isinstance(rightChild, (literal_node.LiteralNode, math_node.MathNode, variable_node.VariableNode)): raise syntax_error.SyntaxError('Invalid Statement') return math_node.MathNode(leftChild, rightChild, token) elif token == self.ASSIGNMENT_TOKEN: return assignment_node.AssignmentNode(self.__parse(tokens), self.__parse(tokens), self.symTbl, token) elif token.isdigit(): return literal_node.LiteralNode(token) elif token.isidentifier(): return variable_node.VariableNode(token, self.symTbl) else: raise syntax_error.SyntaxError('Invalid token ' + token) pass
def emit(self): """ Prints an infiex string representation of the source code that is contained as root nodes in parseTree. :return None """ for node in self.parseTrees: str = print_node.PrintNode(node).emit() print(str)
def __parse(self, tokens): """ The recursive parser that builds the parse tree from one line of source code. :param tokens: The tokens from the source line separated by whitespace in a list of strings. :exception: raises a syntax_error.SyntaxError with the message 'Incomplete statement' if the statement is incomplete (e.g. there are no tokens left and this method was called). :exception: raises a syntax_error.SyntaxError with the message 'Invalid token {token}' if an unrecognized token is encountered (e.g. not one of the tokens listed above). :return: """ if len(tokens) <= 0: raise (syntax_error.SyntaxError("Invalid Expression")) current = tokens[0] if len(tokens) > 0: if type(tokens) is str: tokens = None else: tokens.pop(0) if current == self.ASSIGNMENT_TOKEN: if len(tokens) > 0: return assignment_node.AssignmentNode(self.__parse(tokens.pop(0)),self.__parse(tokens),self.symTbl,'=') else: raise syntax_error.SyntaxError('Incomplete statement') elif current in self.MATH_TOKENS: return math_node.MathNode(self.__parse(tokens),self.__parse(tokens), current) elif current == self.PRINT_TOKEN: if len(tokens)>0: return print_node.PrintNode(self.__parse(tokens)) else: return print_node.PrintNode() elif current.isdigit(): return literal_node.LiteralNode(current) elif current.isalpha(): return variable_node.VariableNode(current,self.symTbl) elif current == self.COMMENT_TOKEN: pass elif current is None: raise syntax_error.SyntaxError('Incomplete statement') else: raise syntax_error.SyntaxError('Invalid token ' + current)
def __parse(self, tokens): """ The recursive parser that builds the parse tree from one line of source code. :param tokens: The tokens from the source line separated by whitespace in a list of strings. :exception: raises a syntax_error.SyntaxError with the message 'Incomplete statement' if the statement is incomplete (e.g. there are no tokens left and this method was called). :exception: raises a syntax_error.SyntaxError with the message 'Invalid token {token}' if an unrecognized token is encountered (e.g. not one of the tokens listed above). :return: the object of one of node classes based on the type token. Node classes: literal_node.LiteralNode, variable_node.VariableNode, assignment_node.AssignmentNode, print_node.PrintNode, math_node.MathNode """ if len(tokens) is 0: raise syntax_error.SyntaxError('Incomplete statement') token = tokens.pop() if token.isdigit(): return literal_node.LiteralNode(token) elif token.isidentifier(): return variable_node.VariableNode(token, self.symTbl) elif token is self.ASSIGNMENT_TOKEN: return assignment_node.AssignmentNode(self.__parse(tokens), self.__parse(tokens), self.symTbl, token) elif token is self.PRINT_TOKEN: if len(tokens) > 0: return print_node.PrintNode(self.__parse(tokens)) else: return print_node.PrintNode() elif token in self.MATH_TOKENS: return math_node.MathNode(self.__parse(tokens), self.__parse(tokens), token) else: raise syntax_error.SyntaxError('Invalid token ' + token)
def __parse(self, tokens): """ The recursive parser that builds the parse tree from one line of source code. :param tokens: The tokens from the source line separated by whitespace in a list of strings. :exception: raises a syntax_error.SyntaxError with the message 'Incomplete statement' if the statement is incomplete (e.g. there are no tokens left and this method was called). :exception: raises a syntax_error.SyntaxError with the message 'Invalid token {token}' if an unrecognized token is encountered (e.g. not one of the tokens listed above). :return: """ if len(tokens) == 0: return elif tokens[0].isidentifier(): node = variable_node.VariableNode(tokens[0], self.symTbl) self.parseTrees.append(node) elif tokens[0].isdigit(): node = literal_node.LiteralNode(int(tokens[0])) self.parseTrees.append(node) elif tokens[0] == '=': node = assignment_node.AssignmentNode(self.parseTrees.pop(), self.parseTrees.pop(), self.symTbl, tokens[0]) self.parseTrees.append(node) elif tokens[0] == '@': node = print_node.PrintNode(self.parseTrees.pop()) self.parseTrees.append(node) elif tokens[0] in self.MATH_TOKENS: x = self.parseTrees.pop() y = self.parseTrees.pop() if not isinstance(x, (variable_node.VariableNode, literal_node.LiteralNode, math_node.MathNode)): raise syntax_error.SyntaxError('Incomplete Statement') if not isinstance(y, (variable_node.VariableNode, literal_node.LiteralNode, math_node.MathNode)): raise syntax_error.SyntaxError('Incomplete Statement') node = math_node.MathNode(x, y, tokens[0]) self.parseTrees.append(node) else: raise syntax_error.SyntaxError("Invalid token") self.__parse(tokens[1:]) """
def parse(self): """ The public parse is responsible for looping over the lines of source code and constructing the parseTree, as a series of calls to the helper function that are appended to this list. It needs to handle and display any syntax_error.SyntaxError exceptions that get raised. : return None """ count = 1 fh = open(self.srcFile) for i in fh: try: self.lineNum = count tokens = i.split() if i[0] == '#' or tokens == []: count += 1 continue elif any(self.MATH_TOKENS) in tokens: if len(tokens) < 3: raise syntax_error.SyntaxError("Incomplete Statement") if '=' in tokens[1:]: count += 1 raise syntax_error.SyntaxError("Invalid Token") if i[0] == '=' or i[0] == '@': count += 1 if len(tokens) == 1: if tokens[0] == '@': node = print_node.PrintNode( literal_node.LiteralNode(' ')) self.parseTrees.append(node) else: if '@' in tokens[1:]: raise syntax_error.SyntaxError( "Bad assignment expression") raise syntax_error.SyntaxError( "Incomplete Statement") self.__parse(tokens[::-1]) else: count += 1 if not (i[0] in self.MATH_TOKENS): raise syntax_error.SyntaxError("Invalid Token") except syntax_error.SyntaxError as syn: self.syntaxError = True print("Line ", self.lineNum, " ", syn)
def parse(self): """ The public parse is responsible for looping over the lines of source code and constructing the parseTree, as a series of calls to the helper function that are appended to this list. It needs to handle and display any syntax_error.SyntaxError exceptions that get raised. : return None """ file = open(self.srcFile) for line in file: self.lineNum += 1 tokens = line.split() # empty line if len(tokens) == 0: continue # assignment statement if tokens[0] == self.ASSIGNMENT_TOKEN: # lack of tokens if len(tokens) < 3: self.syntaxError = True # error message: Incomplete statement print("\nFile \"%s\", line %d" % (self.srcFile, self.lineNum), file=sys.stderr) print(" %sSyntaxError: Incomplete statement" % line, file=sys.stderr) continue # left token is not valid variable name if not tokens[1].isidentifier(): self.syntaxError = True # error message: Bad assignment to non-variable print("\nFile \"%s\", line %d" % (self.srcFile, self.lineNum), file=sys.stderr) print(" %sSyntaxError: Bad assignment to non-variable" % line, file=sys.stderr) continue # construct parse tree for expression on the right expression = self.__parse(tokens[2:]) # error raised during the construction of parse tree if isinstance(expression, syntax_error.SyntaxError): # print out the error message print("\nFile \"%s\", line %d" % (self.srcFile, self.lineNum), file=sys.stderr) print(" %sSyntaxError: %s" % (line, expression), file=sys.stderr) else: # create a new AssignmentNode self.parseTrees.append( assignment_node.AssignmentNode( variable_node.VariableNode(tokens[1], self.symTbl), expression, self.symTbl, tokens[0])) # print statement elif tokens[0] == self.PRINT_TOKEN: # empty expression if len(tokens) == 1: self.parseTrees.append(print_node.PrintNode(None)) else: # construct parse tree for the expression expression = self.__parse(tokens[1:]) # create a new PrintNode self.parseTrees.append(print_node.PrintNode(expression)) # comment line elif tokens[0] == self.COMMENT_TOKEN: continue else: self.syntaxError = True # error message: Invalid token print("\nFile \"%s\", line %d" % (self.srcFile, self.lineNum), file=sys.stderr) print(" %sSyntaxError: Invalid token %s" % (line, tokens[0]), file=sys.stderr) file.close()