예제 #1
0
 private void LinkStates(DFAState src, DFAState dst, CharacterClassElement el)
 {
     AdjList[src][el] = dst;
 }
예제 #2
0
 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);
 }
예제 #3
0
 internal IList<NFAState> Move(NFAState moveState, CharacterClassElement input)
 {
     var s = new List<NFAState>();
     s.Add(moveState);
     return Move(s, input);
 }
예제 #4
0
        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();
        }
예제 #5
0
        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;
        }