Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Delete more now dead code
  • Loading branch information
stephentoub committed Nov 17, 2021
commit 502b5059c3644dbe77875905d6ae41645421b2ad
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ private DfaMatchingState<TSetType> Delta<TTransition>(string input, int i, DfaMa
minterms.Length : // mintermId = minterms.Length represents \Z (last \n)
_partitions.GetMintermID(c);

TSetType minterm = (uint)mintermId < minterms.Length ?
TSetType minterm = (uint)mintermId < (uint)minterms.Length ?
minterms[mintermId] :
_builder._solver.False; // minterm=False represents \Z

Expand Down Expand Up @@ -692,7 +692,7 @@ uint GetCharKindWithAnchor(string input, int i)
{
Debug.Assert(_asciiCharKinds is not null);

if ((uint)i >= input.Length)
if ((uint)i >= (uint)input.Length)
{
return CharKind.StartStop;
}
Expand All @@ -708,7 +708,7 @@ uint GetCharKindWithAnchor(string input, int i)

uint[] asciiCharKinds = _asciiCharKinds;
return
nextChar < asciiCharKinds.Length ? asciiCharKinds[nextChar] :
nextChar < (uint)asciiCharKinds.Length ? asciiCharKinds[nextChar] :
_builder._solver.And(GetMinterm(nextChar), _builder._wordLetterPredicateForAnchors).Equals(_builder._solver.False) ? 0 : //apply the wordletter predicate to compute the kind of the next character
CharKind.WordLetter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1424,152 +1424,6 @@ internal bool StartsWithLoop(int upperBoundLowestValue = 1)
};
}

/// <summary>
/// Gets the string prefix that the regex must match or the empty string if such a prefix does not exist.
/// Sets ignoreCase = true when the prefix works under case-insensitivity.
/// For example if the input prefix is "---" it sets ignoreCase=false,
/// if the prefix is "---[aA][bB]" it returns "---AB" and sets ignoreCase=true
/// </summary>
internal string GetFixedPrefix(CharSetSolver css, string culture, out bool ignoreCase)
{
ignoreCase = false;
StringBuilder prefix = new();
bool doneWithoutIgnoreCase = false;
bool doneWithIgnoreCase = false;
foreach (S x in GetPrefixSequence())
{
BDD bdd = _builder._solver.ConvertToCharSet(css, x);
char character = (char)bdd.GetMin();
// Check if the prefix extends without ignore case: the set is a single character
if (!doneWithoutIgnoreCase && !css.IsSingleton(bdd))
{
doneWithoutIgnoreCase = true;
}
if (!doneWithIgnoreCase)
{
// Check if the prefix extends with ignore case: ignoring case doesn't change the set
if (css.ApplyIgnoreCase(css.CharConstraint(character), culture).Equals(bdd))
{
// Turn ignoreCase on when the prefix extends only under ignore case
if (doneWithoutIgnoreCase)
{
ignoreCase = true;
}
}
else
{
doneWithIgnoreCase = true;
}
}
// Append the character when the prefix extends in either of the ways
if (!doneWithoutIgnoreCase || !doneWithIgnoreCase)
prefix.Append(character);
else
break;
}
return prefix.ToString();
}

private IEnumerable<S> GetPrefixSequence()
{
List<SymbolicRegexNode<S>> paths = new();
HashSet<SymbolicRegexNode<S>> nextPaths = new();

paths.Add(this);
while (true)
{
bool done = false;
Debug.Assert(paths.Count > 0, "The generator should have ended when any path fails to extend.");
// Generate the next set from one path
S next;
if (!GetNextPrefixSet(ref paths, ref nextPaths, ref done, out next))
{
// A path didn't have a next set as supported by this algorithm
yield break;
}
if (!_builder._solver.IsSatisfiable(next))
{
yield break;
}
while (paths.Count > 0)
{
// For all other paths check that they produce the same set
S newSet;
if (!GetNextPrefixSet(ref paths, ref nextPaths, ref done, out newSet) || !newSet.Equals(next))
{
// Either a path didn't have a next set as supported by this algorithm, or the next set was not equal
yield break;
}
}
// At this point all paths generated equal next sets
yield return next;
if (done)
{
// Some path had no continuation, end the prefix
yield break;
}
else
{
Debug.Assert(paths.Count == 0, "Not all paths were considered for next set.");
paths.AddRange(nextPaths);
nextPaths.Clear();
}
}
}

private bool GetNextPrefixSet(ref List<SymbolicRegexNode<S>> paths, ref HashSet<SymbolicRegexNode<S>> nextPaths, ref bool done, out S set)
{
while (paths.Count > 0)
{
SymbolicRegexNode<S> node = paths[paths.Count - 1];
paths.RemoveAt(paths.Count - 1);
switch (node._kind)
{
case SymbolicRegexKind.Singleton:
Debug.Assert(node._set is not null);
set = node._set;
done = true; // No continuation, done after the next set
return true;
case SymbolicRegexKind.Concat:
Debug.Assert(node._left is not null && node._right is not null);
if (!node._left.CanBeNullable)
{
if (node._left.GetFixedLength() == 1)
{
set = node._left.GetStartSet();
// Left side had just one character, can use just right side as path
nextPaths.Add(node._right);
return true;
}
else
{
// Left side may need multiple steps to get through. However, it is safe
// (though not complete) to forget the right side and just expand the path
// for the left side.
paths.Add(node._left);
break;
}
}
else
{
// Left side may be nullable, can't extend the prefix
set = _builder._solver.False; // Not going to be used
return false;
}
case SymbolicRegexKind.Or:
case SymbolicRegexKind.And:
Debug.Assert(node._alts is not null);
// Handle alternatives as separate paths
paths.AddRange(node._alts);
break;
default:
set = _builder._solver.False; // Not going to be used
return false; // Cut prefix immediately for unhandled node
}
}
set = _builder._solver.False; // Not going to be used
return false;
}

/// <summary>Get the predicate that covers all elements that make some progress.</summary>
internal S GetStartSet() => _startSet;
Expand Down