public static int UnbalancedBrackets(string articleText, out int bracketLength)
{
bool templWithUB = TemplateExists(GetAllTemplates(articleText), TemplatesWithUnbalancedBrackets);
// [ and ] are used to replace the [ or ] in external link text, which gives correct markup
// replace back to avoid matching as unbalanced brackets
articleText = HideNestedBrackets.Replace(articleText, m => (m.Value.Contains("93") ? "] " : "[ "));
// remove all <math>, <code> stuff etc. where curly brackets are used in singles and pairs
articleText = Tools.ReplaceWithSpaces(articleText, WikiRegexes.MathPreSourceCodeComments);
// some templates deliberately use unbalanced brackets within their parameters
if(templWithUB)
articleText = Tools.ReplaceWithSpaces(articleText, TemplatesWithUnbalancedBrackets);
bracketLength = 2;
int unbalancedfound = UnbalancedBrackets(articleText, "{{", "}}", DoubleCurlyBrackets);
if (unbalancedfound > -1)
return unbalancedfound;
unbalancedfound = UnbalancedBrackets(articleText, "[[", "]]", DoubleSquareBrackets);
if (unbalancedfound > -1)
return unbalancedfound;
bracketLength = 1;
// Performance: check through whole text counting single brackets, only run detailed checks if find unbalanced brackets
int square=0, curly=0, round=0, chevron=0;
bool hasUnbalanced = false;
foreach(char c in articleText.ToCharArray())
{
// if more closing that opening then have found unbalanced brackets
if(c == '[')
square++;
else if(c == ']')
{
square--;
if(square < 0)
{
hasUnbalanced = true;
break;
}
}
else if(c == '{')
curly++;
else if(c == '}')
{
curly--;
if(curly < 0)
{
hasUnbalanced = true;
break;
}
}
else if (c == '(')
round++;
else if (c == ')')
{
round--;
if(round < 0)
{
hasUnbalanced = true;
break;
}
}
else if (c == '<')
chevron++;
else if (c == '>')
{
chevron--;
if(chevron < 0)
{
hasUnbalanced = true;
break;
}
}
}
// if > 0 residual, means more opening brackets than closing
if (!hasUnbalanced && square == 0 && curly == 0 && round == 0 && chevron == 0)
return -1;
// if here have found an unbalanced single bracket so run the compare
unbalancedfound = UnbalancedBrackets(articleText, "{", "}", SingleCurlyBrackets);
if (unbalancedfound > -1)
return unbalancedfound;
unbalancedfound = UnbalancedBrackets(articleText, "[", "]", SingleSquareBrackets);
if (unbalancedfound > -1)
return unbalancedfound;
unbalancedfound = UnbalancedBrackets(articleText, "(", ")", SingleRoundBrackets);
if (unbalancedfound > -1)
return unbalancedfound;
// look for unbalanced tags
unbalancedfound = UnbalancedBrackets(articleText, "<", ">", Tags);
if (unbalancedfound > -1)
return unbalancedfound;
return -1;
}