ArgInfo constructor

ArgInfo(
  1. TagContext tc,
  2. String data, {
  3. bool idFirst = true,
  4. bool stringFirst = true,
})

Parses the given string.

  • idFirst: whether ID can be the first argument
  • stringFirst: whether string can be the first argument

Notice: if idFirst or stringFirst is true, the first argument can not be a name-value pair.

If both are false, you can use parse instead. It is simpler.

Implementation

factory ArgInfo(TagContext tc, String data,
    {bool idFirst = true, bool stringFirst = true}) {
  if (!idFirst && !stringFirst)
    return ArgInfo._('', false, parseArgs(data));

  String? first;
  bool isID = false;

  if ((data = data.trim()).isNotEmpty) {
    final c0 = data.codeUnitAt(0), len = data.length;
    if (stringFirst && (c0 == $double_quote || c0 == $single_quote)) {
      for (int i = 1; i < len; ++i) {
        final cc = data.codeUnitAt(i);
        if (cc == c0) {
          first = data.substring(1, i);
          data = data.substring(i + 1);
          break; //done
        }
        if (cc == $backslash && i + 1 < len)
          ++i; //skip
      }
    } else if (idFirst) {
      int i = 0;
      for (; i < len && isValidVarCharCode(data.codeUnitAt(i), i == 0); ++i)
        ;
      if (i > 0) {
        first = data.substring(0, i);
        data = data.substring(i).trim();
        isID = true;
        if (!data.isEmpty && data.codeUnitAt(0) == $equal)
          tc.error("Unexpected '=' after an ID, $first"); //highlight common error
      }
    }
  }

  if (first != null)
    return ArgInfo._(first, isID, parseArgs(data));

  final sb = StringBuffer("The first argument must be ");
  if (idFirst) {
    sb.write("an ID");
    if (stringFirst)
      sb.write(" or ");
  }
  if (stringFirst)
    sb.write("a string");
  tc.error(sb.toString());
}