A format for expressing an ordered list of integers is to use a comma separated list of either

 individual integers
 Or a range of integers denoted by the starting integer separated from the end integer in the range by a dash, '-'. (The range includes all integers in the interval including both endpoints)
 The range syntax is to be used only for, and for every range that expands to more than two values.
Example

The list of integers:

 -6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20
Is accurately expressed by the range expression:

 -6,-3-1,3-5,7-11,14,15,17-20
(And vice-versa).



Task

Expand the range description:

  -6,-3--1,3-5,7-11,14,15,17-20 

Note that the second element above,
is the range from minus 3 to minus 1. 



Related task

   Range extraction


\ Given a low and high limit, create an array containing the numbers in the
\ range, inclusive:
: n:gen-range \ low hi -- a
  \ make sure they are in order:
  2dup n:> if swap then
  \ fill the array with the values:
  [] ' a:push 
  2swap loop ;
 
\ Take a string, either "X" or "X-Y", and correctly return either a number (if
\ "X") or an array of numbers (if "X-Y"):
: n:expand-one \ s -- n | a[n,..m]
  \ First see if we can parse a number.  This works in the "X" case:
  dup >n null? if
    \ Failed >n because it's (possibly) "X-Y"
    drop
    \ not a valid number, might be a range
    \ We'll use a capturing regex to handle the different cases correctly:
    /(-?[0-9]+)-(-?[0-9]+)/ tuck r:match 
 
    \ If the regex matches three (the whole string, plus the two captured
    \ expressions) then it's a valid "X-Y":
    3 n:= if
      1 r:@ >n swap 2 r:@ >n nip
      \ generate the range:
      n:gen-range
    else
      \ The regex didn't match, so we got garbage.  Therefore, return a 'null':
      drop null
    then
  else
    \ It was a "X", just drop the original string:
    nip
  then 
  ;
 
\ Take an array (possibly) containing other arrays, and flatten any contained
\ arrays so the result is a simple array:
: a:flatten \ a1 -- a2
  [] >r
  (
    nip
    array?  if
      a:flatten r> swap a:+ >r
    else
      r> swap a:push >r
    then
  ) a:each drop r> ;
 
\ Take a comma-delimited string of ranges, and expand it into an array of
\ numbers:
: n:range-expand \ str -- a
  "," s:/
  ' n:expand-one a:map
  a:flatten ;
 
\ Process a list:
"-6,-3--1,3-5,7-11,14,15,17-20" 
n:range-expand
\ print the expanded list:
. cr bye