/// <summary> /// Parses a group, searching for any reference and dereference operators. Operators and operands are /// replaced with the reference/dereferenced value. /// </summary> /// <param name="group">The group to parse.</param> /// <param name="limit">The index of the group to parse up to. Used by the ParseAssignmentGroup method.</param> /// <returns>A TException on failure, otherwise null.</returns> TException ParseReferencesOfGroup(Group group, int limit = -1) { int limitToUse = limit < 0 ? group.Count - 1 : limit; int index; while (true) { // Search from right to left for the first reference or dereference character int refIndex = group.LastIndexOf(TType.REFERENCE_CHARACTER.ToString(), limitToUse), derefIndex = group.LastIndexOf(TType.DEREFERENCE_CHARACTER.ToString(), limitToUse); char character; // Used so we know what operation we're carrying out later if (refIndex < 0) { index = derefIndex; character = TType.DEREFERENCE_CHARACTER; } else if (derefIndex < 0) { index = refIndex; character = TType.REFERENCE_CHARACTER; } else { if (refIndex > derefIndex) { index = refIndex; character = TType.REFERENCE_CHARACTER; } else { index = derefIndex; character = TType.DEREFERENCE_CHARACTER; } } if (index < 0) break; if (index + 1 > group.Count) return new TException(this, "Invalid expression term '" + character + "' at end of statement"); // If the operand is not a variable, return a TException (can't dereference values) TType variable = TType.Parse(this, group[index + 1]); if (variable is TException) return variable as TException; if (!(variable is TVariable)) { if (character == TType.REFERENCE_CHARACTER) return new TException(this, "Attempted creation of reference to value", "expected variable identifier"); else return new TException(this, "Attempted dereference of value", "expected variable identifier"); } if (character == TType.REFERENCE_CHARACTER) group[index] = new TVariable("reference", variable); else { group[index] = ((TVariable)variable).Value; if (!(group[index] is TVariable) && !(group[index] is TFunction)) return new TException(this, "Dereference of value type variable", "expected reference"); } group.RemoveAt(index + 1); limitToUse = limit < 0 ? group.Count - 1 : limit; } return null; }