iparse method

(Json, int) iparse(
  1. int state,
  2. int j,
  3. FContext context,
  4. IList<FContext> stack,
)
inherited

Implementation

(Json, int) iparse(
  int state,
  int j,
  FContext context,
  IList<FContext> stack,
) {
  // No tail recursion so we must loop
  int iState = state;
  int iJ = j;
  FContext iContext = context;
  IList<FContext> iStack = stack;

  while (true) {
    final i = reset(iJ);
    checkpoint(iState, i, iContext, iStack);

    final c = at(i);

    if (iStack.size > _MaxDepth) {
      die(i, 'JSON max depth ($_MaxDepth) exceeded');
    }

    if (c == '\n') {
      newline(i);
      iJ = i + 1;
    } else if (c == ' ' || c == '\t' || c == '\r') {
      iJ = i + 1;
    } else if (iState == _DATA) {
      // we are inside an object or array expecting to see data
      if (c == '[') {
        iState = _ARRBEG;
        iJ = i + 1;
        iStack = iStack.prepended(iContext);
        iContext = FContext.array(i);
      } else if (c == '{') {
        iState = _OBJBEG;
        iJ = i + 1;
        iStack = iStack.prepended(iContext);
        iContext = FContext.object(i);
      } else if ((c >= '0' && c <= '9') || c == '-') {
        iJ = _parseNum(i, iContext);
        iState = iContext.isObject ? _OBJEND : _ARREND;
      } else if (c == '"') {
        iJ = parseString(i, iContext);
        iState = iContext.isObject ? _OBJEND : _ARREND;
      } else if (c == 't') {
        iContext.addValueAt(_parseTrue(i), i);
        iState = iContext.isObject ? _OBJEND : _ARREND;
        iJ = i + 4;
      } else if (c == 'f') {
        iContext.addValueAt(_parseFalse(i), i);
        iState = iContext.isObject ? _OBJEND : _ARREND;
        iJ = i + 5;
      } else if (c == 'n') {
        iContext.addValueAt(_parseNull(i), i);
        iState = iContext.isObject ? _OBJEND : _ARREND;
        iJ = i + 4;
      } else {
        die(i, 'expected json value');
      }
    } else if ((c == ']' && (iState == _ARREND || iState == _ARRBEG)) ||
        (c == '}' && (iState == _OBJEND || iState == _OBJBEG))) {
      // we are inside an array or object and have seen a key or a closing
      // brace, respectively.
      if (iStack.isEmpty) {
        return (iContext.finishAt(i), i + 1);
      } else {
        final ctxt2 = iStack[0];
        ctxt2.addValueAt(iContext.finishAt(i), i);

        iState = ctxt2.isObject ? _OBJEND : _ARREND;
        iJ = i + 1;
        iContext = ctxt2;
        iStack = iStack.tail();
      }
    } else if (iState == _KEY) {
      // we are in an object expecting to see a key.
      if (c == '"') {
        iJ = parseString(i, iContext);
        iState = _SEP;
      } else {
        die(i, 'expected "');
      }
    } else if (iState == _SEP) {
      // we are in an object just after a key, expecting to see a colon.
      if (c == ':') {
        iState = _DATA;
        iJ = i + 1;
      } else {
        die(i, 'expected :');
      }
    } else if (iState == _ARREND) {
      // we are in an array, expecting to see a comma (before more data).
      if (c == ',') {
        iState = _DATA;
        iJ = i + 1;
      } else {
        die(i, 'expected ] or ,');
      }
    } else if (iState == _OBJEND) {
      // we are in an object, expecting to see a comma (before more data).
      if (c == ',') {
        iState = _KEY;
        iJ = i + 1;
      } else {
        die(i, 'expected } or ,');
      }
    } else if (iState == _ARRBEG) {
      // we are starting an array, expecting to see data or a closing bracket.
      iState = _DATA;
      iJ = i;
    } else {
      // we are starting an object, expecting to see a key or a closing brace.
      iState = _KEY;
      iJ = i;
    }
  }
}