function v = parseComplexToken(tok)
    % Accept forms: a, bi, a+bi, a-bi, (a+bi), with i/j, scientific notation.
    t = strtrim(tok);
    if isempty(t), v = NaN; return; end
    % strip parentheses
    if t(1)=='(' && t(end)==')'
        t = strtrim(t(2:end-1));
    end
    % unify imaginary unit to 'i'
    t = strrep(t,'J','i'); t = strrep(t,'j','i'); t = strrep(t,'I','i');

    % quick exact real number?
    vreal = str2double(t);
    if ~isnan(vreal)
        v = vreal; return;
    end

    % regex components
    num = '([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)';
    % a +/- b i
    m = regexp(t, ['^\s*' num '\s*([+-])\s*' num '\s*i\s*$'], 'tokens', 'once');
    if ~isempty(m)
        a = str2double(m{1});
        signch = m{2}; bpart = m{3};
        bi = str2double([signch bpart]);
        v = complex(a, bi); return;
    end
    % pure imaginary: b i
    m = regexp(t, ['^\s*' num '\s*i\s*$'], 'tokens', 'once');
    if ~isempty(m)
        b = str2double(m{1});
        v = complex(0, b); return;
    end
    % handle cases like +i or -i
    m = regexp(t, '^\s*([+-]?)i\s*$', 'tokens', 'once');
    if ~isempty(m)
        s = m{1}; if isempty(s), s = '+'; end
        v = complex(0, str2double([s '1'])); return;
    end

    % last resort: try str2num (slower; eval-based)
    tmp = str2num(t); %#ok<ST2NM>
    if ~isempty(tmp) && isscalar(tmp)
        v = tmp; return;
    end

    % give up
    v = NaN;
end