protected override IParseResult TryGetTokenWithoutNullCheck(IStringStream inputStream, out IToken token) { token = null; if (EnforceCharacterRangeSeparatorEscaping && IsCharacterRangeSeparator(inputStream)) { return(new FailureParseResult(inputStream.CurrentPosition, RegSeedErrorType.InvalidRange)); } var rangeResult = _primitiveParser.TryParseCharacterRange(inputStream); if (rangeResult.IsSuccess) { var rangeTokenLength = (int)(inputStream.CurrentPosition - _initialStreamPosition); token = new CharacterRangeToken(rangeResult.Value, inputStream.CurrentPosition, rangeTokenLength); return(new SuccessParseResult()); } if (!rangeResult.IsSuccess && rangeResult.ErrorType != RegSeedErrorType.None) { return(rangeResult); } var characterResult = _primitiveParser.TryParseCharacter(inputStream); if (!characterResult.IsSuccess) { return(characterResult); } var characterTokenLength = (int)(inputStream.CurrentPosition - _initialStreamPosition); token = new CharacterToken(characterResult.Value, inputStream.CurrentPosition, characterTokenLength); return(new SuccessParseResult()); }
public void GetType_ThrowsTypeAccessException_WhenEnumTypeNotRegexTokenType() { var token = new CharacterRangeToken(null, 0, 0); Assert.Throws <TypeAccessException>(() => token.GetType <TestColor>()); }
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; }