code: function parseArg(rawArg) {
    // clean up whitespace
    let arg = rawArg.trim()
      // replace comma entity with comma
      .replace(/&comma;/g, ',')
      // repair extra escape sequences; note only commas strictly need
      // escaping, but we allow any other char to be escaped since its
      // likely users will do this
      .replace(/\\(.)/g, '\$1')
      ;
    // basic argument descriptor
    let a = {
      name: arg,
      value: '',
      literal: false
    };
    // detect literal value (must be String or Number)
    let fc = arg[0];
    if (fc === '-') {
      fc = arg[1];
    }
    if (fc >= '0' && fc <= '9') {
      fc = '#';
    }
    switch(fc) {
      case "'":
      case '"':
        a.value = arg.slice(1, -1);
        a.literal = true;
        break;
      case '#':
        a.value = Number(arg);
        a.literal = true;
        break;
    }
    // if not literal, look for structured path
    if (!a.literal) {
      a.rootProperty = root$0(arg);
      // detect structured path (has dots)
      a.structured = isPath$0(arg);
      if (a.structured) {
        a.wildcard = (arg.slice(-2) == '.*');
        if (a.wildcard) {
          a.name = arg.slice(0, -2);
        }
      }
    }
    return a;
  }
docs: Parses an individual argument, and returns an argument metadata object
  with the following fields:
  
  {
  value: 'prop',        // property/path or literal value
  literal: false,       // whether argument is a literal
  structured: false,    // whether the property is a path
  rootProperty: 'prop', // the root property of the path
  wildcard: false       // whether the argument was a wildcard '.*' path
  }
  
  @param {string} rawArg The string value of the argument
  @return {!MethodArg} Argument metadata object
  @private