public int?CheckValidity(bool canThrow = true) { var parentheses = new Stack <int>(); int bracketDeep = 0; int parentheseDeep = 0; for (int i = 0; i < EncodedString.Length; i++) { var chr = EncodedString[i]; if (chr == '#' || chr == '~') { if (i + 1 >= EncodedString.Length || !char.IsDigit(EncodedString[i + 1])) { if (canThrow) { throw new InvalidPatternException("Attempt a digit after '" + chr + "'", i); } else { return(i); } } } if (chr == '{') { bracketDeep++; } else if (chr == '}') { bracketDeep--; } if (chr == '[') { parentheseDeep++; parentheses.Push(i); } else if (chr == ']') { parentheseDeep--; int last = parentheses.Pop(); var sub = EncodedString.Substring(i + 1, last - 1 - i); if (string.IsNullOrEmpty(sub) || !sub.All(char.IsDigit)) { if (canThrow) { throw new InvalidPatternException("Attempt a number between [ and ]", last); } else { return(i); } } } } if (bracketDeep != 0) { if (canThrow) { throw new InvalidPatternException("'{' not closed"); } else { return(0); } } if (parentheseDeep != 0) { if (canThrow) { throw new InvalidPatternException("'[' not closed"); } else { return(0); } } return(null); }