public SyntacticalDFAState(ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> lookup, GrammarSymbolSet symbols) { if (lookup == null) { throw new ArgumentNullException("lookup"); } this.lookup = lookup; this.symbols = symbols; }
/// <summary> /// Constructs the initial look-ahead for the transitions. /// </summary> /// <remarks></remarks> public void ConstructInitialLookahead(GrammarSymbolSet grammarSymbols, Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleVocabulary) { /* * * Left-recursive rules will use the relevant rule * paths within their projections within a loop to avoid * stack overflow. * */ bool includeRules = this.RootLeaf.Veins.LeftRecursionType != ProductionRuleLeftRecursionType.None; var result = new ControlledDictionary <GrammarVocabulary, PredictionTree>(); this.LookAhead = result; if (includeRules) { /* * * On left-recursive rules, the requirements change. * * * The rules must be considered at the start to * ensure that the left recursive branches * can be switched 'off' to allow for reductions * to function properly. * */ foreach (var key in this.Veins.Keys) { var targets = this.Veins[key]; if (targets.Any(k => k.GetRecursionType() != ProductionRuleLeftRecursionType.None && this.RootLeaf == this)) { var intersection = key.Intersect(this.Veins.DFAOriginState.OutTransitions.FullCheck); var reducedRules = key.GetRuleVariant().GetSymbols().Select(k => (IGrammarRuleSymbol)k).Select(k => new { Node = fullSeries.GetRuleNodeFromFullSeries(k.Source), Symbol = k }).Where(k => k.Node.HasBeenReduced || k.Node == k.Node.RootLeaf && k.Node.Veins.LeftRecursionType != ProductionRuleLeftRecursionType.None).Select(k => k.Symbol); var ruleVar = new GrammarVocabulary(key.symbols, reducedRules.ToArray()); intersection |= (key.GetTokenVariant() | ruleVar); if (!intersection.IsEmpty) { result._Add(intersection, targets); } } else { DoReductionAware(fullSeries, result, key); } } } else { foreach (var key in this.Veins.Keys.ToArray()) { DoReductionAware(fullSeries, result, key); } } /* * * Lexical ambiguity handling follows after the full transition table is known. * */ SyntacticAnalysisCore.CreateLexicalAmbiguityTransitions(grammarSymbols, result, null, this, fullSeries, ruleVocabulary); }
internal bool CalculateTerminalAmbiguities( Dictionary <SyntacticalDFAState, PredictionTreeLeaf> allLeaves, ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> ruleDFAStates, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup, GrammarSymbolSet grammarSymbols) { var ambiguities = ObtainTerminalAmbiguities(allLeaves, ruleDFAStates, ruleLookup, grammarSymbols); /* * * First step, reduce the ambiguity data provided to us. * * * This is done here versus in the ObtainTerminalAmbiguities * due to the 'research' nature of this process. * * * It might have to be rewritten or the information added * back in. * */ var ambiguityRewrite = (from ambigKeysValue in ambiguities from reductionTuple in ambigKeysValue.Value from pathSet in reductionTuple.Item1 select new { AmbiguousTransition = ambigKeysValue.Keys.Key1, TyingPaths = ambigKeysValue.Keys.Key2, FollowAmbiguity = new PredictionTreeFollow(pathSet.Item2, this) //ConstructInitialFollow(this, ambigKeysValue.Keys.Key1, reductionTuple, allLeaves, ruleDFAStates, ruleLookup), }).ToArray(); foreach (var rewrite in ambiguityRewrite) { if (rewrite.FollowAmbiguity.InitialPaths.All(initialPath => initialPath.CurrentNode.Veins.DFAOriginState.IsEdge)) { continue; } List <PredictionTreeFollow> currentSet; if (!this.followAmbiguities.TryGetValue(rewrite.AmbiguousTransition, rewrite.TyingPaths, out currentSet)) { followAmbiguities.Add(rewrite.AmbiguousTransition, rewrite.TyingPaths, currentSet = new List <PredictionTreeFollow>()); } currentSet.Add(rewrite.FollowAmbiguity); } return(followAmbiguities.Count > 0); }
private void ObtainTerminalAmbiguitiesOnPath( PredictionTreeBranch sourceMasterPath, Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries, ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> ruleDFAs, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup, FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> > transitionTableResult, GrammarSymbolSet grammarSymbols) { var ambiguousSymbols = grammarSymbols.AmbiguousSymbols.ToList(); Stack <Tuple <int, PredictionTreeBranch> > toProcess = new Stack <Tuple <int, PredictionTreeBranch> >(); var fullCheck = this.Veins.Keys.Aggregate(GrammarVocabulary.UnionAggregateDelegate); /* * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Kick things off with the master path, this is derived * * from the incoming states from the parent rule. * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ toProcess.Push(Tuple.Create(0, sourceMasterPath)); //foreach (var transition in this.Value.Keys) // foreach (var target in this.Value[transition]) // toProcess.Push(new PredictionTreeBranch(sourceMasterPath.Take(sourceMasterPath.Depth).Concat(target).ToList(), sourceMasterPath.Depth, true, false, sourceMasterPath.GetDeviationsUpTo(sourceMasterPath.Depth))); HashSet <PredictionTreeBranch> seen = new HashSet <PredictionTreeBranch>(); while (toProcess.Count > 0) { var currentPathTuple = toProcess.Pop(); var currentPath = currentPathTuple.Item2; if (currentPath.Depth == 0) { continue; } if (currentPath.CurrentNode.Veins.Keys.Aggregate(GrammarVocabulary.UnionAggregateDelegate).Intersect(fullCheck).IsEmpty) { continue; } /* * * Walk up the tree one level into the state that * follows the current rule in whatever the current * calling rule might be. * */ var incomingTransitions = currentPath.FollowTransition(fullSeries, ruleLookup[currentPath.CurrentNode.Veins.Rule], ruleLookup, true, false, true, true); /* * * Aggregate the transitions from our previously * calculated LL(1) look-ahead information. * */ /* * * On the state following this rule, gather up the * targets which do overlap one or more of our * transitions. * */ var fullAmbiguityContext = incomingTransitions.FullCheck | fullCheck; var intersectionPoints = (from t in incomingTransitions.Keys let intersection = t.Intersect(fullCheck) where !intersection.IsEmpty from path in incomingTransitions[t] select new { Intersection = intersection, Path = path }).ToArray(); var overlap = GrammarVocabulary.NullInst; if ((fullAmbiguityContext != null && !fullAmbiguityContext.IsEmpty) && grammarSymbols.IsGrammarPotentiallyAmbiguous(fullAmbiguityContext)) { foreach (var ambiguity in ambiguousSymbols) { var localIntersect = fullCheck & ambiguity.AmbiguityKey; var incomingIntersect = incomingTransitions.FullCheck & ambiguity.AmbiguityKey; if (localIntersect.IsEmpty || incomingIntersect.IsEmpty) { /* If the intersection isn't present on one or the other sides; then, for the purposes of * this follow check, the union would not be relevant, it would likely be identified within the * prediction upon the state itself. */ continue; } var aggregateIntersect = fullAmbiguityContext & ambiguity.AmbiguityKey; var overlapIntersect = overlap & ambiguity.AmbiguityKey; if (aggregateIntersect.Equals(ambiguity.AmbiguityKey) && !overlapIntersect.Equals(ambiguity.AmbiguityKey)) { /* */ var ambiguityIntersection = (from t in incomingTransitions.Keys let intersection = t.Intersect(incomingIntersect) where !intersection.IsEmpty from path in incomingTransitions[t] select new { Intersection = intersection, Path = path }).ToArray(); var ambiguityVocabulary = new GrammarVocabulary(grammarSymbols, ambiguity); foreach (var intersectingPoint in ambiguityIntersection) { var path = intersectingPoint.Path; var intersection = localIntersect; if (path.Equals(currentPath)) { continue; } /* Notify the nodes of the ambiguities so their state-machines can be patched up. * This is done explicitly to avoid the ambiguity cropping up and allowing it everywhere, * which is incorrect. If it shows up where it's not supposed to, we have a logic error * somwehere. */ foreach (var node in (from ambigPath in PushIntersection(sourceMasterPath, transitionTableResult, toProcess, seen, currentPathTuple, currentPath, path, intersection, ambiguityVocabulary) select ambigPath.CurrentNode).Distinct().ToArray()) { node.DenoteLexicalAmbiguity(ambiguity); } } ambiguity.Occurrences++; overlap |= aggregateIntersect; } } } foreach (var intersectingPoint in intersectionPoints) { var path = intersectingPoint.Path; var intersection = intersectingPoint.Intersection; if (path.Equals(currentPath)) { continue; } PushIntersection(sourceMasterPath, transitionTableResult, toProcess, seen, currentPathTuple, currentPath, path, intersection).ToArray(); } } }
internal MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > > ObtainTerminalAmbiguities( Dictionary <SyntacticalDFAState, PredictionTreeLeaf> fullSeries, ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> ruleDFAs, Dictionary <IOilexerGrammarProductionRuleEntry, GrammarVocabulary> ruleLookup, GrammarSymbolSet grammarSymbols) { if (!this.Veins.DFAOriginState.IsEdge) { return(new MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > >()); } var tempDictionary = new MultikeyedDictionary <PredictionTreeBranch, GrammarVocabulary, Tuple <int[], PredictionTree> >(); var rootNode = fullSeries[ruleDFAs[this.Rule]]; var currentIncoming = new List <PredictionTreeBranch>(rootNode.incoming); var reductions = rootNode.PointsOfReduction.ToArray(); if (reductions.Length > 0) { } var totalIncoming = new HashSet <PredictionTreeBranch>(); Dictionary <PredictionTree, PredictionTree> uniqueSet = new Dictionary <PredictionTree, PredictionTree>(); foreach (var path in currentIncoming) { var transitionTableResult = new FiniteAutomataMultiTargetTransitionTable <GrammarVocabulary, Tuple <int, PredictionTreeBranch> >(); var masterPathChop = new PredictionTreeBranch(path.Take(path.Depth).Concat(new[] { this }).ToArray(), path.Depth, false, false); masterPathChop.SetDeviations(path.GetDeviationsUpTo(path.Depth)); ObtainTerminalAmbiguitiesOnPath(masterPathChop, fullSeries, ruleDFAs, ruleLookup, transitionTableResult, grammarSymbols); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ * Construct the sequence of Path->Grammar->PathSets based * * off of the table provided by the ObtainTerminalAmbiguitiesOnPath. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **/ foreach (var transition in transitionTableResult.Keys) { var epDepthLookup = (from entry in transitionTableResult[transition] group entry.Item1 by entry.Item2).ToDictionary(k => k.Key, v => v.ToArray()); //int minDepth; //var uniqueCurrent = GetUniqueDPathSet(uniqueSet, transitionTableResult, transition, epDepthLookup); //var subPath = new PredictionTreeBranch(path.Skip(minDepth).ToList(), path.Depth - minDepth, minDepth: path.MinDepth); tempDictionary.TryAdd(path, transition, Tuple.Create((from epDepth in transitionTableResult[transition] select epDepth.Item1).ToArray(), GetFollowDPathSet(transitionTableResult, transition, epDepthLookup))); } } var regrouping = (from ksvp in tempDictionary group new { Path = ksvp.Keys.Key1, Set = ksvp.Value } by ksvp.Keys.Key2).ToDictionary(k => k.Key, v => v.ToArray()); /* * foreach (var pathSet in from key in regrouping.Keys * let value = regrouping[key] * from r in value * select r.Set) * pathSet.Item2.FixAllPaths();//*/ var comparisons = (from key in regrouping.Keys let value = regrouping[key] let kRewrite = from r in value select r.Set let commonalities = PredictionTree.GetCompoundRightSideSimilarities(kRewrite) select new { Commonalities = commonalities, Transition = key }).ToDictionary(k => k.Transition, v => v.Commonalities); var resultDictionary = new MultikeyedDictionary <GrammarVocabulary, int, List <Tuple <Tuple <int[], PredictionTree>[], int[]> > >(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \ * Once we're done, we need to rebuild the paths with the MinDepth set to * * their current Depth. This is to ensure that it the PathSets don't try * * to reduce more than necessary. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Then we take that set and perform a right-hand-side comparison between * * the elements. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This will be used later to reduce the walking necessary to isolate the * * proper machine to use to disambiguate the look-ahead. * \ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **/ foreach (var comparison in comparisons.Keys) { var comparisonElements = comparisons[comparison]; foreach (var memberCount in comparisonElements.Keys) { var comparisonElement = comparisonElements[memberCount]; resultDictionary.Add(comparison, memberCount, comparisonElement); } } return(resultDictionary); }
public SyntacticalDFARootState(IOilexerGrammarProductionRuleEntry entry, ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> lookup, GrammarSymbolSet symbols) : base(lookup, symbols) { this.entry = entry; }
public GrammarSymbolComparer(GrammarSymbolSet grammarSymbols) { this._grammarSymbols = grammarSymbols; }
public SyntacticalNFAState(ControlledDictionary <IOilexerGrammarProductionRuleEntry, SyntacticalDFARootState> lookup, GrammarSymbolSet symbols) { this.lookup = lookup; this.symbols = symbols; }