private static bool InContext(
ITreeAdaptor adaptor,
string[] tokenNames,
object t,
string context)
{
if (Regex.IsMatch(context, DotDot))
{
// don't allow "..", must be "..."
throw new ArgumentException("invalid syntax: ..");
}
if (Regex.IsMatch(context, DoubleEtc))
{
// don't allow double "..."
throw new ArgumentException("invalid syntax: ... ...");
}
context = context.Replace("...", " ... "); // ensure spaces around ...
context = context.Trim();
string[] nodes = context.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int ni = nodes.Length - 1;
t = adaptor.GetParent(t);
while (ni >= 0 && t != null)
{
if (nodes[ni].Equals("..."))
{
// walk upwards until we see nodes[ni-1] then continue walking
if (ni == 0)
{
// ... at start is no-op
return true;
}
string goal = nodes[ni - 1];
object ancestor = GetAncestor(adaptor, tokenNames, t, goal);
if (ancestor == null)
return false;
t = ancestor;
ni--;
}
string name = tokenNames[adaptor.GetType(t)];
if (!name.Equals(nodes[ni]))
{
//System.Console.Error.WriteLine("not matched: " + nodes[ni] + " at " + t);
return false;
}
// advance to parent and to previous element in context node list
ni--;
t = adaptor.GetParent(t);
}
if (t == null && ni >= 0)
return false; // at root but more nodes to match
return true;
}