/// <summary>
/// Handles the C# switch-type SELECT-type statements.
/// </summary>
/// <remarks>
/// This methods processes the SELECT-type statements that behave like if...elseif statements.
/// </remarks>
/// <param name="p_astSelect">The SELECT statement to process.</param>
private void HandleSelectString(ITree p_astSelect)
{
m_intSelectDepth++;
string strExpression = (string)Run(p_astSelect.GetChild(0), true);
if (p_astSelect.Type == ModScriptParser.SELECTVAR)
{
strExpression = m_sicContext.GetVar(strExpression);
}
if (strExpression != null)
{
Regex rgxWhitespace = new Regex(@"\s");
strExpression = rgxWhitespace.Replace(strExpression, " ");
Regex rgxAdjacentSpaces = new Regex(@" +");
strExpression = rgxAdjacentSpaces.Replace(strExpression, " ");
}
List <KeyValuePair <string, ITree> > lstCases = new List <KeyValuePair <string, ITree> >();
ITree astDefaultCase = null;
for (Int32 i = 1; i < p_astSelect.ChildCount; i++)
{
ITree astCase = p_astSelect.GetChild(i);
switch (astCase.Type)
{
case ModScriptParser.CASE:
StringBuilder stbMatchValue = new StringBuilder();
for (Int32 j = 0; j < astCase.ChildCount - 1; j++)
{
stbMatchValue.Append(Run(astCase.GetChild(j), true));
if (j < astCase.ChildCount - 2)
{
stbMatchValue.Append(" ");
}
}
string strMatchValue = stbMatchValue.ToString();
lstCases.Add(new KeyValuePair <string, ITree>(strMatchValue, astCase.GetChild(astCase.ChildCount - 1)));
break;
case ModScriptParser.DEFAULT:
astDefaultCase = astCase.GetChild(0);
break;
default:
throw new Exception(String.Format("Unrecognized SELECT case type: {0}. Expecting CASE or DEFAULT. ({1},{2})", astCase.Text, astCase.Line, astCase.CharPositionInLine));
}
}
bool booMatched = false;
foreach (KeyValuePair <string, ITree> kvpCase in lstCases)
{
//if we previously matched a CASE, but are still examining
// CASEs, it is because there was no Break statement and we
// fell through to the subsequent CASEs. if that is the case,
// don't check the condition, just execute the code.
// (when we fall through we execute subsequent blocks until
// the next Break statement without caring about the CASE
// conditions)
if (booMatched || String.Equals(strExpression, kvpCase.Key))
{
booMatched = true;
Run(kvpCase.Value);
if (m_booReturnSet || m_booGotoSet)
{
return;
}
if (m_booBreakSet)
{
break;
}
}
}
if ((!booMatched || !m_booBreakSet) && (astDefaultCase != null))
{
Run(astDefaultCase);
if (m_booReturnSet || m_booGotoSet)
{
return;
}
}
m_booBreakSet = false;
m_intSelectDepth--;
}