private void LinkStates(DFAState src, DFAState dst, CharacterClassElement el) { AdjList[src][el] = dst; }
private void LinkStates(NFAState src, NFAState dst, CharacterClassElement el) { if (!AdjList[src].ContainsKey(el) || AdjList[src][el] == null) AdjList[src][el] = new HashSet<NFAState>(); AdjList[src][el].Add(dst); }
internal IList<NFAState> Move(NFAState moveState, CharacterClassElement input) { var s = new List<NFAState>(); s.Add(moveState); return Move(s, input); }
internal IList<NFAState> Move(IList<NFAState> moveStates, CharacterClassElement input) { var rSet = new List<NFAState>(); foreach (var state in moveStates) { if (AdjList[state].ContainsKey(input)) rSet.AddRange(AdjList[state][input]); } return rSet.Distinct().ToList(); }
public static NormaliseCharacterClassResult NormaliseCharacterClasses(IList<CharacterClass> classes) { var rStruct = new NormaliseCharacterClassResult() { Alphabet = new HashSet<CharacterClassElement>(), Mapping = new Dictionary<CharacterClass, CharacterClass>() }; //Need to create the list of start/end class elements var rangeTokenList = classes.SelectMany(cl => cl.Elements) .SelectMany(el => new CharacterRangeToken[] { new CharacterRangeToken() { Value = el.Start, SourceElement = el, Type = TokenType.Start }, new CharacterRangeToken() { Value = el.End, SourceElement = el, Type = TokenType.End } }) .OrderBy(tk => tk.Value) //stable sort, start tokens always before end tokens .ToList(); //Now break up the ranges //Mapping of old char class els into new components var activeRanges = new Dictionary<CharacterClassElement, ISet<CharacterClassElement>>(); var inactiveRanges = new Dictionary<CharacterClassElement, ISet<CharacterClassElement>>(); var previousToken = new CharacterRangeToken() { Value = char.MinValue, Type = TokenType.Start }; var first = true; foreach (var token in rangeTokenList) { //make our new class var newRange = new CharacterClassElement(previousToken.Value, token.Value); //work out [), (], etc if (previousToken.Type == TokenType.Start && token.Type == TokenType.Start) { newRange = new CharacterClassElement(previousToken.Value, (char)(token.Value - 1)); } else if (previousToken.Type == TokenType.End && token.Type == TokenType.End) { newRange = new CharacterClassElement((char)(previousToken.Value + 1), token.Value); } else if (previousToken.Type == TokenType.End && token.Type == TokenType.Start) { newRange = new CharacterClassElement((char)(previousToken.Value + 1), (char)(token.Value - 1)); } //Make sure there's actually a worthwile range here //Also, skip first so we don't put the \0-token range in //If they have an any char class, this will get added by the logic anyway if (newRange.End >= newRange.Start && !first) { rStruct.Alphabet.Add(newRange); //Now attach it to anything that wants it //Skipped on first iter foreach (var ccel in activeRanges.Keys) activeRanges[ccel].Add(newRange); } //Now add new source classes switch (token.Type) { case TokenType.Start: if (!activeRanges.ContainsKey(token.SourceElement)) activeRanges.Add(token.SourceElement, new HashSet<CharacterClassElement>()); break; case TokenType.End: if (activeRanges.ContainsKey(token.SourceElement)) { inactiveRanges[token.SourceElement] = activeRanges[token.SourceElement]; activeRanges.Remove(token.SourceElement); } break; } previousToken = token; first = false; } //fix cclass mappings foreach (var cClass in classes) { rStruct.Mapping[cClass] = new CharacterClass() { IsNegated = false }; foreach (var newRange in cClass.Elements.SelectMany(el => inactiveRanges[el])) rStruct.Mapping[cClass].Elements.Add(newRange); //If negated, swap to a non-negated class if (cClass.IsNegated) { var newCClass = new CharacterClass(); newCClass.Elements.UnionWith( rStruct.Alphabet.Except(rStruct.Mapping[cClass].Elements)); rStruct.Mapping[cClass] = newCClass; } } return rStruct; }