code: private List<Variable> parseAssignRange(Sequence sequence, TokenList tokens, TokenList.Token t0) {
          // find assignment symbol
          TokenList.Token tokenAssign = t0.next;
          while( tokenAssign != null && tokenAssign.symbol != Symbol.ASSIGN ) {
              tokenAssign = tokenAssign.next;
          }
  
          if( tokenAssign == null )
              throw new ParseError("Can't find assignment operator");
  
          // see if it is a sub matrix before
          if( tokenAssign.previous.symbol == Symbol.PAREN_RIGHT ) {
              TokenList.Token start = t0.next;
              if( start.symbol != Symbol.PAREN_LEFT )
                  throw new ParseError(("Expected left param for assignment"));
              TokenList.Token end = tokenAssign.previous;
              TokenList subTokens = tokens.extractSubList(start,end);
              subTokens.remove(subTokens.getFirst());
              subTokens.remove(subTokens.getLast());
  
              handleParentheses(subTokens,sequence);
  
              List<TokenList.Token> inputs = parseParameterCommaBlock(subTokens, sequence);
  
              if (inputs.isEmpty())
                  throw new ParseError("Empty function input parameters");
  
              List<Variable> range = new ArrayList<>();
              addSubMatrixVariables(inputs, range);
              if( range.size() != 1 && range.size() != 2 ) {
                  throw new ParseError("Unexpected number of range variables.  1 or 2 expected");
              }
              return range;
          }
  
          return null;
      }
docs: See if a range for assignment is specified.  If so return the range, otherwise return null
  
  Example of assign range:
  a(0:3,4:5) = blah
  a((0+2):3,4:5) = blah