When `[example attr1="value1" attr2 attr3="value3" attr4]` is parsed, the `$atts` parameter yields:

    $atts = array (
        'attr1' => 'value1',
              0 => 'attr2',
        'attr3' => 'value3',
              1 => 'attr4'
    );

You can normalize this like so, then you can call `shortcode_atts` on it.

    if (!function_exists('normalize_empty_atts')) {
        function normalize_empty_atts ($atts) {
            foreach ($atts as $attribute => $value) {
                if (is_int($attribute)) {
                    $atts[strtolower($value)] = true;
                    unset($atts[$attribute]);
                }
            }
            return $atts;
        }
    }

    function paragraph_shortcode ($atts, $content = null) {
        extract(shortcode_atts(
            array (
                'last' => ''
            ),
            normalize_empty_atts($atts)
        ));
        
        return '<p class="super-p'
            .($last ? ' last' : '')
            .'">'
            .do_shortcode($content)
            .'</p>';
    }
    
    add_shortcode('paragraph', 'paragraph_shortcode');

**Other notes:**

 - `[paragraph last]` would make `$last = true`. `[paragraph last="1"]` would make `$last = '1'`.
 - Attributes are case-insensitive, so `[paragraph LAST]` is equivalent to `[paragraph last]`.
 - Attributes cannot be purely numeric, so the `foreach` loop I created is safe against integer-indexed attributes.