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); } }
public DfaNode AddTransition(char symbol) { var node = new DfaNode(); this.transitions.Add(symbol, node); return(node); }
public void AddPolicyEdge(object state, DfaNode node) { if (PolicyEdges == null) { PolicyEdges = new Dictionary <object, DfaNode>(); } PolicyEdges.Add(state, node); }
public void AddLiteral(string literal, DfaNode node) { if (Literals == null) { Literals = new Dictionary <string, DfaNode>(StringComparer.OrdinalIgnoreCase); } Literals.Add(literal, node); }
public DfaNode GetDfa(NfaNode nfaNode) { DfaNode firstDfaNode = GetFirstDfaNode(nfaNode); BuildDfaInternal(firstDfaNode, new List <DfaNode> { firstDfaNode }); MarkIsFinal(firstDfaNode, nfaNode); return(firstDfaNode); }
private void MarkIsFinal(DfaNode firstDfaNode, NfaNode nfaNode) { NfaNode lastNfaNode = GetLastNfaNode(nfaNode); if (firstDfaNode.NfaNodes.Contains(lastNfaNode)) { firstDfaNode.IsFinal = true; } MarkIsFinalInternal(firstDfaNode, lastNfaNode); }
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); }
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)); }
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); }
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); }
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); }
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); }
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); } }
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); }
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); }
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); } }
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++; } }
public DfaNode UpdateTransitnion(char symbol, DfaNode node) { this.transitions[symbol] = node; return(node); }
static DfaNode FindEquivalent(DfaNode state, ICollection <DfaNode> register) => register.FirstOrDefault(s => s.IsEquivalentTo(state));
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(); } }
public static bool Recognize(this DfaNode node, string word) { var(endNode, pathLength) = node.Walk(word); return(pathLength == word.Length && endNode.IsFinal); }
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); }