Returns an AST where all operations of lower precedence are finalized.

def _start_operation(self, ast, operation, precedence):
        """
        Returns an AST where all operations of lower precedence are finalized.
        """
        if TRACE_PARSE:
            print('   start_operation:', repr(operation), 'AST:', ast)

        op_prec = precedence[operation]
        while True:
            if ast[1] is None:
                # [None, None, x]
                if TRACE_PARSE: print('     start_op: ast[1] is None:', repr(ast))
                ast[1] = operation
                if TRACE_PARSE: print('     --> start_op: ast[1] is None:', repr(ast))
                return ast

            prec = precedence[ast[1]]
            if prec > op_prec:  # op=&, [ast, |, x, y] -> [[ast, |, x], &, y]
                if TRACE_PARSE: print('     start_op: prec > op_prec:', repr(ast))
                ast = [ast, operation, ast.pop(-1)]
                if TRACE_PARSE: print('     --> start_op: prec > op_prec:', repr(ast))
                return ast

            if prec == op_prec:  # op=&, [ast, &, x] -> [ast, &, x]
                if TRACE_PARSE: print('     start_op: prec == op_prec:', repr(ast))
                return ast

            if not (inspect.isclass(ast[1]) and issubclass(ast[1], Function)):
                # the top ast node should be a function subclass at this stage
                raise ParseError(error_code=PARSE_INVALID_NESTING)

            if ast[0] is None:  # op=|, [None, &, x, y] -> [None, |, x&y]
                if TRACE_PARSE: print('     start_op: ast[0] is None:', repr(ast))
                subexp = ast[1](*ast[2:])
                new_ast = [ast[0], operation, subexp]
                if TRACE_PARSE: print('     --> start_op: ast[0] is None:', repr(new_ast))
                return new_ast

            else:  # op=|, [[ast, &, x], ~, y] -> [ast, &, x, ~y]
                if TRACE_PARSE: print('     start_op: else:', repr(ast))
                ast[0].append(ast[1](*ast[2:]))
                ast = ast[0]
                if TRACE_PARSE: print('     --> start_op: else:', repr(ast))