Example #1
0
        private void BuildDfaInternal(DfaNode dfaNode, List <DfaNode> previous)
        {
            List <char> values = GetValuesFromNfaNodes(dfaNode.NfaNodes, c => c != EPS, nfaL => nfaL.LinkValue);

            foreach (char value in values)
            {
                var newDfaNode = new DfaNode();

                newDfaNode.NfaNodes = GetValuesFromNfaNodes(dfaNode.NfaNodes, c => c == value,
                                                            nfaL => nfaL.NfaNode, addEpsCondition: true).Distinct().ToList();

                DfaNode possibleSameDfaNode = previous
                                              .FirstOrDefault(pr => pr.NfaNodes.SequenceEqual(newDfaNode.NfaNodes));
                if (possibleSameDfaNode != null)
                {
                    dfaNode.Links.Add(new DfaNodeLink(possibleSameDfaNode, value));

                    continue;
                }

                previous.Add(newDfaNode);
                dfaNode.Links.Add(new DfaNodeLink(newDfaNode, value));

                BuildDfaInternal(newDfaNode, previous);
            }
        }
Example #2
0
    public DfaNode AddTransition(char symbol)
    {
        var node = new DfaNode();

        this.transitions.Add(symbol, node);
        return(node);
    }
Example #3
0
    public void AddPolicyEdge(object state, DfaNode node)
    {
        if (PolicyEdges == null)
        {
            PolicyEdges = new Dictionary <object, DfaNode>();
        }

        PolicyEdges.Add(state, node);
    }
Example #4
0
    public void AddLiteral(string literal, DfaNode node)
    {
        if (Literals == null)
        {
            Literals = new Dictionary <string, DfaNode>(StringComparer.OrdinalIgnoreCase);
        }

        Literals.Add(literal, node);
    }
Example #5
0
        public DfaNode GetDfa(NfaNode nfaNode)
        {
            DfaNode firstDfaNode = GetFirstDfaNode(nfaNode);

            BuildDfaInternal(firstDfaNode, new List <DfaNode> {
                firstDfaNode
            });
            MarkIsFinal(firstDfaNode, nfaNode);

            return(firstDfaNode);
        }
Example #6
0
        private void MarkIsFinal(DfaNode firstDfaNode, NfaNode nfaNode)
        {
            NfaNode lastNfaNode = GetLastNfaNode(nfaNode);

            if (firstDfaNode.NfaNodes.Contains(lastNfaNode))
            {
                firstDfaNode.IsFinal = true;
            }

            MarkIsFinalInternal(firstDfaNode, lastNfaNode);
        }
Example #7
0
        private DfaNode GetFirstDfaNode(NfaNode nfaNode)
        {
            var dfaNode = new DfaNode();

            dfaNode.NfaNodes = GetValuesFromNfaNode(nfaNode, c => c == EPS, nfaL => nfaL.NfaNode,
                                                    values: new List <NfaNode> {
                nfaNode
            }).Distinct().ToList();

            return(dfaNode);
        }
Example #8
0
            private DfaNode CreateDfaNode(Node node, DfaTransition transition, ExecutionPath predicatePath)
            {
                var tuple = (node, transition, predicatePath);

                if (_dfaNodesDictionary.TryGetValue(tuple, out var dfaNode))
                {
                    return(dfaNode);
                }

                return(_dfaNodesDictionary[tuple] = new DfaNode(node, transition, predicatePath));
            }
Example #9
0
        public Dfa.DfaTable BuildDfa()
        {
            Nfa.Nfa nfa = nfaWorker.Compile();

            // -- from here build DFA out of NFA
            List <DfaNode> done   = new List <DfaNode>();
            List <Link>    to_add = (new[] { new Link(null, 0, new DfaNode(nfa.StartNode)) }).ToList();

            while (to_add.Any())
            {
                // build closures for incoming nodes
                to_add.Select(it => it.Target).ForEach(it => it.BuildClosure());

                List <Link> new_links = new List <Link>();

                foreach (Link link in to_add)
                {
                    // check if we already have that DFA node
                    DfaNode existing = done.SingleOrDefault(it => it.SameNfaCore(link.Target));

                    if (existing == null)
                    {
                        done.Add(link.Target);

                        if (link.Source != null)
                        {
                            link.Source.ConnectTo(link.Edge, link.Target);
                        }
                        new_links.AddRange(link.Target.ComputeLinks());
                    }
                    else
                    {
                        link.Source.ConnectTo(link.Edge, existing);
                    }
                }

                to_add = new_links;
            }

            done.ZipWithIndex().ForEach(it => it.Item1.Index = it.Item2);

            var dfa = new Dfa.DfaTable(done.Count);

            foreach (DfaNode node in done)
            {
                dfa.SetAccepting(node.Index, node.AcceptingValues);
                node.CreateTransitions(dfa);
            }

            return(dfa);
        }
Example #10
0
    public static (DfaNode EndNode, int PathLength) Walk(this DfaNode node, string word)
    {
        var curr = node;
        int i;

        for (i = 0; i < word.Length; i++)
        {
            var next = curr.GetTransitnion(word[i]);
            if (next == null)
            {
                break;
            }
            curr = next;
        }

        return(curr, i);
    }
Example #11
0
    public bool IsEquivalentTo(DfaNode q)
    {
        if ((this.IsFinal != q.IsFinal) || (this.TransitionCount != q.TransitionCount))
        {
            return(false);
        }

        foreach (var pair in this.transitions)
        {
            var qNext = q.GetTransitnion(pair.Key);
            if (qNext == null || !pair.Value.IsEquivalentTo(qNext))
            {
                return(false);
            }
        }

        return(true);
    }
Example #12
0
    public static DfaNode Insert(this DfaNode node, string word)
    {
        var curr = node;

        foreach (var symbol in word)
        {
            var next = curr.GetTransitnion(symbol);

            if (next == null)
            {
                next = curr.AddTransition(symbol);
            }

            curr = next;
        }

        curr.IsFinal = true;
        return(node);
    }
Example #13
0
    static void ReplaceOrRegister(DfaNode state, ICollection <DfaNode> register)
    {
        var(symbol, child) = state.LastChild;

        if (child.HasTransitions)
        {
            ReplaceOrRegister(child, register);
        }

        var equiv = FindEquivalent(child, register);

        if (equiv != null)
        {
            state.UpdateTransitnion(symbol, equiv);
        }
        else
        {
            register.Add(child);
        }
    }
Example #14
0
        private bool IsPassedStringThroughDfa(string str, DfaNode dfaNode)
        {
            if (str.Length == 0)
            {
                return(dfaNode.IsFinal);
            }

            foreach (DfaNodeLink childNode in dfaNode.Links)
            {
                if (childNode.LinkValue == str.First())
                {
                    bool isMatched = IsPassedStringThroughDfa(str.Substring(1, str.Length - 1), childNode.DfaNode);
                    if (isMatched)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #15
0
    public static DfaNode ConstructMinAcyclicDFA(IEnumerable <string> words)
    {
        var register = new HashSet <DfaNode>();
        var start    = new DfaNode();

        foreach (var word in words)
        {
            var(lastState, pathLength) = start.Walk(word);
            var commonPrefix  = word.Substring(0, pathLength);
            var currentSuffix = word.Substring(pathLength);

            if (lastState.HasTransitions)
            {
                ReplaceOrRegister(lastState, register);
            }
            lastState.Insert(currentSuffix);
        }

        ReplaceOrRegister(start, register);

        return(start);
    }
Example #16
0
        private void MarkIsFinalInternal(DfaNode node, NfaNode nfaNode, List <DfaNode> previous = null)
        {
            if (previous == null)
            {
                previous = new List <DfaNode>();
            }

            previous.Add(node);

            foreach (DfaNodeLink childNode in node.Links)
            {
                if (childNode.DfaNode.NfaNodes.Contains(nfaNode))
                {
                    childNode.DfaNode.IsFinal = true;
                }

                if (previous.Contains(childNode.DfaNode))
                {
                    continue;
                }

                MarkIsFinalInternal(childNode.DfaNode, nfaNode, previous);
            }
        }
Example #17
0
            private void AddParentsWithMatchingLiteralConstraints(List <DfaNode> nextParents, DfaNode parent, RoutePatternParameterPart parameterPart, IReadOnlyList <RoutePatternParameterPolicyReference> parameterPolicyReferences)
            {
                // The list of parameters that fail to meet at least one IParameterLiteralNodeMatchingPolicy.
                var hasFailingPolicy = parent.Literals.Keys.Count < 32 ?
                                       (stackalloc bool[32]).Slice(0, parent.Literals.Keys.Count) :
                                       new bool[parent.Literals.Keys.Count];

                // Whether or not all parameters have failed to meet at least one constraint.
                for (var i = 0; i < parameterPolicyReferences.Count; i++)
                {
                    var reference       = parameterPolicyReferences[i];
                    var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference);
                    if (parameterPolicy is IParameterLiteralNodeMatchingPolicy constraint)
                    {
                        var literalIndex = 0;
                        var allFailed    = true;
                        foreach (var literal in parent.Literals.Keys)
                        {
                            if (!hasFailingPolicy[literalIndex] && !constraint.MatchesLiteral(parameterPart.Name, literal))
                            {
                                hasFailingPolicy[literalIndex] = true;
                            }

                            allFailed &= hasFailingPolicy[literalIndex];

                            literalIndex++;
                        }

                        if (allFailed)
                        {
                            // If we get here it means that all literals have failed at least one policy, which means we can skip checking policies
                            // and return early. This will be a very common case when your constraints are things like "int,length or a regex".
                            return;
                        }
                    }
                }

                var k = 0;

                foreach (var literal in parent.Literals.Values)
                {
                    if (!hasFailingPolicy[k])
                    {
                        nextParents.Add(literal);
                    }
                    k++;
                }
            }
Example #18
0
 public DfaNode UpdateTransitnion(char symbol, DfaNode node)
 {
     this.transitions[symbol] = node;
     return(node);
 }
Example #19
0
 static DfaNode FindEquivalent(DfaNode state, ICollection <DfaNode> register) =>
 register.FirstOrDefault(s => s.IsEquivalentTo(state));
Example #20
0
            private void AddParentsMatchingComplexSegment(RouteEndpoint endpoint, List <DfaNode> nextParents, RoutePatternPathSegment segment, DfaNode parent, RoutePatternParameterPart parameterPart)
            {
                var routeValues = new RouteValueDictionary();

                foreach (var literal in parent.Literals.Keys)
                {
                    if (RoutePatternMatcher.MatchComplexSegment(segment, literal, routeValues))
                    {
                        // If we got here (rare) it means that the literal matches the complex segment (for example the literal is something A-B)
                        // there is another thing we can try here, which is to evaluate the policies for the parts in case they have one (for example {a:length(4)}-{b:regex(\d+)})
                        // so that even if it maps closely to a complex parameter we have a chance to discard it and avoid adding the extra branches.
                        var passedAllPolicies = true;
                        for (var i = 0; i < segment.Parts.Count; i++)
                        {
                            var segmentPart = segment.Parts[i];
                            if (segmentPart is not RoutePatternParameterPart partParameter)
                            {
                                // We skip over the literals and the separator since we already checked against them
                                continue;
                            }

                            if (!routeValues.TryGetValue(partParameter.Name, out var parameterValue))
                            {
                                // We have a pattern like {a}-{b}.{part?} and a literal "a-b". Since we've matched the complex segment it means that the optional
                                // parameter was not specified, so we skip it.
                                Debug.Assert(i == segment.Parts.Count - 1 && partParameter.IsOptional);
                                continue;
                            }

                            if (endpoint.RoutePattern.ParameterPolicies.TryGetValue(partParameter.Name, out var parameterPolicyReferences))
                            {
                                for (var j = 0; j < parameterPolicyReferences.Count; j++)
                                {
                                    var reference       = parameterPolicyReferences[j];
                                    var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference);
                                    if (parameterPolicy is IParameterLiteralNodeMatchingPolicy constraint && !constraint.MatchesLiteral(partParameter.Name, (string)parameterValue))
                                    {
                                        passedAllPolicies = false;
                                        break;
                                    }
                                }
                            }
                        }

                        if (passedAllPolicies)
                        {
                            nextParents.Add(parent.Literals[literal]);
                        }
                    }

                    routeValues.Clear();
                }
            }
Example #21
0
 public static bool Recognize(this DfaNode node, string word)
 {
     var(endNode, pathLength) = node.Walk(word);
     return(pathLength == word.Length && endNode.IsFinal);
 }
Example #22
0
            private void AddRequiredLiteralValue(RouteEndpoint endpoint, List <DfaNode> nextParents, DfaNode parent, RoutePatternParameterPart parameterPart, object requiredValue)
            {
                if (endpoint.RoutePattern.ParameterPolicies.TryGetValue(parameterPart.Name, out var parameterPolicyReferences))
                {
                    for (var k = 0; k < parameterPolicyReferences.Count; k++)
                    {
                        var reference       = parameterPolicyReferences[k];
                        var parameterPolicy = _parameterPolicyFactory.Create(parameterPart, reference);
                        if (parameterPolicy is IOutboundParameterTransformer parameterTransformer)
                        {
                            requiredValue = parameterTransformer.TransformOutbound(requiredValue);
                            break;
                        }
                    }
                }

                var literalValue = requiredValue?.ToString() ?? throw new InvalidOperationException($"Required value for literal '{parameterPart.Name}' must evaluate to a non-null string.");

                AddLiteralNode(_includeLabel, nextParents, parent, literalValue);
            }
 private void AddNode(DfaNode dfaNode)
 {
     _nodesCollection.Add(dfaNode);
 }