static parseParamValue(value, type = true, name = true, desc = true) {
    value = value.trim();

    let match;
    let typeText = null;
    let paramName = null;
    let paramDesc = null;

    // e.g {number}
    if (type) {
      const reg = /^\{([^@]*?)\}(\s+|$)/; // ``@`` is special char in ``{@link foo}``
      match = value.match(reg);
      if (match) {
        typeText = match[1];
        value = value.replace(reg, '');
      } else {
        typeText = '*';
      }
    }

    // e.g. [p1=123]
    if (name) {
      if (value.charAt(0) === '[') {
        paramName = '';
        let counter = 0;
        for (const c of value) {
          paramName += c;
          if (c === '[') counter++;
          if (c === ']') counter--;
          if (counter === 0) break;
        }

        if (paramName) {
          value = value.substr(paramName.length).trim();
        }
      } else {
        match = value.match(/^(\S+)/);
        if (match) {
          paramName = match[1];
          value = value.replace(/^\S+\s*/, '');
        }
      }
    }

    // e.g. this is p1 desc.
    if (desc) {
      match = value.match(/^-?\s*((:?.|\n)*)$/m);
      if (match) {
        paramDesc = match[1];
      }
    }

    assert(typeText || paramName || paramDesc, `param is invalid. param = "${value}"`);

    return {typeText, paramName, paramDesc};
  }
parse param value.
@param {string} value - param value.
@param {boolean} [type=true] if true, contain param type.
@param {boolean} [name=true] if true, contain param name.
@param {boolean} [desc=true] if true, contain param description.
@return {{typeText: string, paramName: string, paramDesc: string}} parsed value.

@example
let value = '{number} param - this is number param';
let {typeText, paramName, paramDesc} = ParamParser.parseParamValue(value);

let value = '{number} this is number return value';
let {typeText, paramDesc} = ParamParser.parseParamValue(value, true, false, true);

let value = '{number}';
let {typeText} = ParamParser.parseParamValue(value, true, false, false);