Пример #1
0
    def __init__(self, variable, expression, symTbl, token):
        """
        Initialize an AssignmentNode.

        :param variable: The variable node (VariableNode)
        :param expression: The expression that represents the value
            the variable will be associated with (LiteralNode,
            MathNode or VariableNode)
        :param symTbl: The symbol table which associates variable
            names (key=str) with values (value=int)
        :param token: The character associated with assignment
            when emitting (str)
        :exception: raises syntax_error.SyntaxError if there is an assignment
            to a non-variable, with the message, 'Bad assignment to non-variable'
        :exception: raises syntax_error.SyntaxError if the expression is bad,
            with the message, 'Bad assignment expression'.
        :return: None
        """

        # first check for syntax errors and raise an appropriate exception
        if not isinstance(variable, variable_node.VariableNode):
            raise syntax_error.SyntaxError('Bad assignment to non-variable')

        if not isinstance(expression,
                          (literal_node.LiteralNode, math_node.MathNode,
                           variable_node.VariableNode)):
            raise syntax_error.SyntaxError('Bad assignment expression')

        self.variable = variable
        self.expression = expression
        self.symTbl = symTbl
        self.token = token
Пример #2
0
    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) < 1:
            return
        firstToken = tokens[0]

        if firstToken is self.COMMENT_TOKEN:
            return

        if firstToken.isdigit():
            node = literal_node.LiteralNode(firstToken)
            self.parseTrees.append(node)

        elif firstToken.isidentifier():
            self.symTbl[firstToken] = ''
            node = variable_node.VariableNode(firstToken, self.symTbl)
            self.parseTrees.append(node)

        elif firstToken == self.ASSIGNMENT_TOKEN:
            first = self.parseTrees.pop()
            second = self.parseTrees.pop()
            valid = self.checkIfPoppedNodesAreValidForAssignmentNode(
                first, second)
            if valid == True:
                node = assignment_node.AssignmentNode(first, second,
                                                      self.symTbl, firstToken)
                self.parseTrees.append(node)
                node.evaluate()
            else:
                self.syntaxError = True
                raise syntax_error.SyntaxError('Incomplete Statement' +
                                               ' line Number ' +
                                               str(self.lineNum))

        elif firstToken in self.MATH_TOKENS:
            first = self.parseTrees.pop()
            second = self.parseTrees.pop()
            valid = self.checkIfPoppedNodesAreValidForMathNode(first, second)
            if valid == True:
                node = math_node.MathNode(first, second, firstToken)
                self.parseTrees.append(node)
            else:
                self.syntaxError = True
                raise syntax_error.SyntaxError('Incomplete Statement' +
                                               ' line Number ' +
                                               str(self.lineNum))

        self.__parse(tokens[1:])
Пример #3
0
    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:
            token = tokens.pop(0)
        else:
            return

        if token is self.COMMENT_TOKEN:
            return None

        elif token is self.PRINT_TOKEN:
            return print_node.PrintNode(self.__parse(tokens))

        elif token.isdigit():
            return literal_node.LiteralNode(token)

        elif token == '=':
            return assignment_node.AssignmentNode(self.__parse(tokens),
                                                  self.__parse(tokens),
                                                  self.symTbl, token)

        elif token in self.MATH_TOKENS:
            left = self.__parse(tokens)
            right = self.__parse(tokens)
            if not isinstance(left,
                              (literal_node.LiteralNode, math_node.MathNode,
                               variable_node.VariableNode)):
                raise syntax_error.SyntaxError('Incomplete expression')
            if not isinstance(right,
                              (literal_node.LiteralNode, math_node.MathNode,
                               variable_node.VariableNode)):
                raise syntax_error.SyntaxError('Incomplete expression')

            return math_node.MathNode(left, right, token)

        elif token.isidentifier():
            return variable_node.VariableNode(token, self.symTbl)
        else:
            raise syntax_error.SyntaxError("Invalid token {" + str(token) +
                                           "}")
Пример #4
0
    def isIncompleteExpression(self, mylist):
        length = len(mylist)
        if length < 3 and mylist[0] in self.MATH_TOKENS:
            self.syntaxError = True
            raise syntax_error.SyntaxError('Incomplete Statement' +
                                           ' line Number ' + str(self.lineNum))
            return True

        if length < 3 and mylist[0] == self.ASSIGNMENT_TOKEN:
            self.syntaxError = True
            raise syntax_error.SyntaxError('Incomplete Statement' +
                                           ' line Number ' + str(self.lineNum))
            return True
        return False
Пример #5
0
    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:])
        """
Пример #6
0
    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)
Пример #7
0
 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)
Пример #8
0
 def validate(self, mylist):
     count = 0
     length = len(mylist)
     for i in mylist:
         count += 1
         if i != self.ASSIGNMENT_TOKEN and i not in self.MATH_TOKENS and i != self.PRINT_TOKEN and not i.isidentifier(
         ) and not i.isdigit():
             self.syntaxError = True
             raise syntax_error.SyntaxError('Invalid token ' + str(i) +
                                            ' line Number ' +
                                            str(self.lineNum))
             return i
         if i == self.PRINT_TOKEN and count <= length and count != 1:
             self.syntaxError = True
             raise syntax_error.SyntaxError('Bad assignment expression' +
                                            ' line Number ' +
                                            str(self.lineNum))
             return i
     return ""
Пример #9
0
    def __init__(self, left, right, token):
        """
        Initialize a MathNode.
        :param left: the left expression (LiteralNode, MathNode, VariableNode)
        :param right: the right expression (LiteralNode, MathNode, VariableNode)
        :param token: the character for the math operation (str)
        :return: None
        """
        if not isinstance(left,
                          (variable_node.VariableNode, math_node.MathNode,
                           literal_node.LiteralNode)):
            raise syntax_error.SyntaxError('Illegal Epression.')

        if not isinstance(right,
                          (variable_node.VariableNode, math_node.MathNode,
                           literal_node.LiteralNode)):
            raise syntax_error.SyntaxError('Illegal Epression.')

        self.left = left
        self.right = right
        self.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:
        """
        # pass
        print('tokens are',tokens)
        token_list = ['+', '-', '*', '//', '#', '=', '@']
        if not tokens:
            raise syntax_error.SyntaxError('Incomplete statement')
        for i in tokens:
            if not i.isdigit() and not i.isidentifier():
                if i not in token_list:
                    raise syntax_error.SyntaxError('Invalid token {i}')
        i =0
        while(i < len(tokens)):
            if tokens[i] == PreTee.COMMENT_TOKEN:
                i+=1

            elif tokens[i].isidentifier():
                variable_node.VariableNode(tokens[i], self.symTbl[tokens[i]])
                i+=1
            elif tokens[i].isdigit():
                literal_node.LiteralNode(tokens[i])
                i+=1
            elif tokens[i] in PreTee.MATH_TOKENS:
                left_val = self.__parse(tokens[i+1])
                right_val = self.__parse(tokens[i+2])
                math_node.MathNode(left_val, right_val, tokens[i])
                i+=2
Пример #11
0
    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)
Пример #12
0
    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
        """
        with open(self.srcFile) as file:
            for line in file:
                self.lineNum += 1
                try:
                    line = line.strip()
                    if '#' in line or line == '':
                        continue
                    myList = line.split()
                    invalidToken = self.validate(myList)

                    s1 = set(self.MATH_TOKENS)
                    s2 = set(myList)

                    if s1.intersection(s2):
                        if self.ASSIGNMENT_TOKEN in myList:
                            if (len(myList) - 1) < 3:
                                self.syntaxError = True
                                raise syntax_error.SyntaxError(
                                    'Incomplete Statement' + ' line Number ' +
                                    str(self.lineNum))

                    if not self.isIncompleteExpression(
                            myList) and invalidToken == "":
                        myList = myList[::-1]
                        self.__parse(myList)
                    else:
                        pass
                        # self.syntaxError = True
                        # raise syntax_error.SyntaxError('Invalid token ' + str(invalidToken) + ' line Number ' + str(self.lineNum))
                except syntax_error.SyntaxError as e:
                    print('***Syntax Error:', e)
Пример #13
0
    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:
        """
        # no token left
        if len(tokens) < 1:
            # error message: Incomplete statement
            self.syntaxError = True
            return syntax_error.SyntaxError("Incomplete statement")

        elif len(tokens) == 1:
            if tokens[0].isdigit():
                return literal_node.LiteralNode(int(tokens[0]))

            elif tokens[0].isidentifier():
                return variable_node.VariableNode(tokens[0], self.symTbl)

            else:
                # error message: Invalid token
                self.syntaxError = True
                return syntax_error.SyntaxError("Invalid token %s" % tokens[0])

        elif tokens[0] in self.MATH_TOKENS:
            # leaf nodes required to construct the left expression parse tree
            leavesNeed = 1

            for i in range(1, len(tokens)):
                if tokens[i].isdigit() or tokens[i].isidentifier():
                    # a leaf node
                    leavesNeed -= 1

                elif tokens[i] in self.MATH_TOKENS:
                    # a interior node, need one more leaf node to construct the
                    # full binary tree
                    leavesNeed += 1

                else:
                    # error message: Invalid token
                    self.syntaxError = True
                    return syntax_error.SyntaxError("Invalid token %s" %
                                                    tokens[i])

                # has all nodes required to construct the left expression
                if leavesNeed == 0:
                    # construct the left and right expression
                    left = self.__parse(tokens[1:i + 1])
                    right = self.__parse(tokens[i + 1:])

                    # error raised in construction of left expression
                    if isinstance(left, syntax_error.SyntaxError):
                        return left

                    # error raised in construction of right expression
                    if isinstance(right, syntax_error.SyntaxError):
                        return right

                    return math_node.MathNode(left, right, tokens[0])

        else:
            # error message: Invalid token
            self.syntaxError = True
            return syntax_error.SyntaxError("Invalid token %s" % tokens[0])