Transform a string into an array based on grouping rules I've got a simple spec for defining character sets, ranges, or wildcards. I'd like to take the string and appropriately create an array based on these rules. I have a solution but I'm sure there is a better way!


Single characters may be used
Sets and ranges are enclosed in brackets []
Sets are comma separated, [1,3,S]
Ranges are hyphenated, [1-3]
Sets and ranges can be combined, [1-3,7,9-10,S]
Wildcard character is - and not enclosed in brackets
Strings can contain the following characters are A-Z 0-9 - .


Example inputs and expected outputs


'ABC' outputs ['A', 'B', 'C']
'S[1-2]-' outputs ['S', '1-2', '-']
'S[1-2]2.0[0-9][1,3,7]S' outputs ['S', '1-2', '2', '.', '0', '0-9', '1,3,7', 'S']
'S[1-2,7]' outputs ['S', '1-2,7']


My implementation:

function stringToArray(code) {
    var exploded = code.split(''),
            charGroups = [],
            tempGroup = '',
            inGroup = false;
    while (exploded.length &gt; 0) {
        var cur = exploded.shift();
        if (cur === '[') {
            inGroup = true;
            continue;
        }
        if (inGroup) {
            if (cur === ']') {
                inGroup = false;
                charGroups.push(tempGroup);
                tempGroup = '';
            } else {
                tempGroup += cur;
            }
        }
        if (!inGroup) {
            if (cur !== ',' &amp;&amp; cur !== '[' &amp;&amp; cur !== ']') {
                charGroups.push(cur);
            }
        }
    }
    return charGroups;
}


Demo fiddle here: http://jsfiddle.net/3q25eps3/
You could perhaps use regular expressions, provided the spec stays simple. For instance

function stringToArray(string) {
  var segments = [];
  string.replace(/(\[([^\]]+)\]|[^,])/g, function (m0, m1, m2) {
    segments.push(m2 || m1); // push bracket content (m2) or single char (m1)
  });
  return segments;
}


The code uses replace to map/scan the string (it doesn't actually bother with replacing anything), since it accepts a callback function.

The pattern used will match either:


The content between [ and ] as a contiguous string: \[([^\]]+)\]
Single, non-comma character outside brackets: [^,]


And due to the g (global) flag in the pattern, it'll repeat matching until the end of the string.

This depends on bracket not being nested or unbalanced (it can't handle that). It's also assumes anything that's not a comma should be captured. I.e. even if the character @ isn't part of the spec, it'll still get treated as a "valid" character and included in the output. Similarly it'll skip over multiple commas in a row, even if such a string is invalid.

So it's kinda rough, and I can't guarantee it'll cover all cases, but it gives the correct output for your test cases.