Exemplo n.º 1
0
    def term(self):
        """Match the grammar for a term."""
        self.stack.append("Factor")
        operator_map = {"*": "*", "DIV": "/", "MOD": "%"}
        cur = self.factor()

        # 0 or more patterns.
        while True:
            if self.current.kind == "*" or self.current.kind == "DIV" or self.current.kind == "MOD":
                if self.current.kind == "*":
                    operator = self.match("*")
                elif self.current.kind == "DIV":
                    operator = self.match("DIV")
                else:
                    operator = self.match("MOD")

                self.stack.append("Factor")
                var = self.factor()

                if isinstance(cur, Number) and isinstance(var, Number):
                    # Constant folding.
                    try:
                        val = int(eval(str(cur.entry.value) + str(operator_map[operator.kind]) + str(var.entry.value)))
                    except ZeroDivisionError:
                        # Divide by 0 error.
                        self.invalid_token(DivideByZero(self.last))
                        break

                    const = Constant(self.integer_type, val)
                    cur = Number(const)
                else:
                    if isinstance(cur, VariableAST) and (
                        isinstance(cur.variable, Array) or isinstance(cur.variable, Record)
                    ):
                        # Trying to perform an operation on non-integers.
                        try:
                            raise InvalidArithmeticOperation(cur, self.last)
                        except InvalidArithmeticOperation as e:
                            self.invalid_token(e)

                    else:
                        cur = Binary(operator.kind, cur, var, self.integer_type)
                        # Remember the token for node in case of run time errors.
                        cur.token = self.last

            else:
                # Pattern ended.
                break

        return cur
Exemplo n.º 2
0
    def expression(self):
        """Match the grammar of an expression."""
        operator = None

        if self.current.kind == "+":
            operator = self.match("+")
        elif self.current.kind == "-":
            operator = self.match("-")

        self.stack.append("Term")
        cur = self.term()
        if operator != None and operator.kind == "-":
            # Negate the expression if needed.
            if isinstance(cur, Number):
                # Constant folding.
                cur = Number(Constant(self.integer_type, eval(str(operator.kind) + str(cur.entry.value))))
            else:
                if isinstance(cur, VariableAST) and (
                    isinstance(cur.variable, Array) or isinstance(cur.variable, Record)
                ):
                    # Trying to perform an operation on non-integers.
                    try:
                        raise InvalidArithmeticOperation(cur, self.last)
                    except InvalidArithmeticOperation as e:
                        self.invalid_token(e)

                else:
                    cur = Binary(operator.kind, Number(Constant(self.integer_type, 0)), cur, self.integer_type)

                    # Remember the token for node in case of run time errors.
                    cur.token = self.last

        # 0 or more patterns.
        while True:
            if self.current.kind in {"+", "-"}:
                if self.current.kind == "+":
                    operator = self.match("+")
                else:
                    operator = self.match("-")

                self.stack.append("Term")
                var = self.term()
                if isinstance(cur, Number) and isinstance(var, Number):
                    # Constant folding.
                    cur = Number(
                        Constant(
                            self.integer_type, eval(str(cur.entry.value) + str(operator.kind) + str(var.entry.value))
                        )
                    )
                else:
                    if isinstance(cur, VariableAST) and (
                        isinstance(cur.variable, Array) or isinstance(cur.variable, Record)
                    ):
                        # Trying to perform an operation on non-integers.
                        try:
                            raise InvalidArithmeticOperation(cur, self.last)
                        except InvalidArithmeticOperation as e:
                            self.invalid_token(e)
                    else:
                        cur = Binary(operator.kind, cur, var, self.integer_type)

                        # Remember token for node in case of run time errors.
                        cur.token = self.last
            else:
                # Pattern ended.
                break

        if cur == None:
            # Return an invalid variable node in case of parsing errors.
            cur = VariableAST("INVALID", Variable(Invalid()))
        return cur