private bool IsCompletedTermConsistentWithNextTerm(NonTerminalObject completedTerm, NonTerminalObject nextTerm, out NonTerminalStack intersection) { intersection = null; if (nextTerm == null) { return(false); } //the above case happens where the rule to be continued is already completed at the start column (next term = null). //this can only happen in a single case: that rule was an epsilon rule. if (completedTerm.NonTerminal != nextTerm.NonTerminal) { return(false); } if (nextTerm.Stack == null && completedTerm.Stack == null) { return(true); } var intersectAlgo = new StackGraphIntersect(); intersection = intersectAlgo.Execute(nextTerm.Stack, completedTerm.Stack); return(intersection != null); }
public NonTerminalObject(NonTerminalObject otherNonTerminalObject) { NonTerminal = otherNonTerminalObject.NonTerminal; if (otherNonTerminalObject.Stack != null) { Stack = otherNonTerminalObject.Stack; //shallow copy } }
public Rule(Rule otherRule) { Name = new NonTerminalObject(otherRule.Name); Production = otherRule.Production.Select(nonterminal => new NonTerminalObject(nonterminal)).ToArray(); HeadPosition = otherRule.HeadPosition; ComplementPosition = otherRule.ComplementPosition; Number = otherRule.Number; Occurrences = otherRule.Occurrences; }
public Rule(int occurrences, string name, string[] prod, int headPos = 0, int compPos = 1, int num = -1) { Name = new NonTerminalObject(name); if (prod != null) { Production = prod.Select(nonterminal => new NonTerminalObject(nonterminal)).ToArray(); } HeadPosition = headPos; ComplementPosition = compPos; Number = num; Occurrences = occurrences; }
private RuleConsistentWithDerivation IsPredictedRuleConsistentWithCurrentDerivation( NonTerminalObject currObject, Rule rule) { //TODO: change later to skip -all- rules whose derivation leads to the empty string. //I.e, A-> B.C , C -> D E. D -> epsilon, E -> epsilon. C itself is not an epsilon rule. //1. states that are the result of a spontenous dot shift (due to nullable production) //have already been added to the agendas in Column.Add() if (rule.IsEpsilonRule() && Grammar.nullableProductions.ContainsKey(currObject)) { return(RuleConsistentWithDerivation.SkipGeneration); } //2. if current stack is empty but predicted stack is not, mismatch - do not predict this rule. if (currObject.IsStackEmpty() && !rule.IsInitialOrDotStack()) { return(RuleConsistentWithDerivation.RuleInconsistent); } if (rule.IsInitialRule()) { var complementPositionObject = rule.Production[rule.ComplementPosition]; //3. if current stack is not empty, but the complement position does not allow for stacks (POS), //mismatch - do not predict this rule. if (!currObject.IsStackEmpty() && Grammar.IsPOS(complementPositionObject.NonTerminal)) { return(RuleConsistentWithDerivation.RuleInconsistent); } } else { //4. if tops of the stacks do not match, continue. e.g created rule PP[PP] -> epsilon, current object: PP[NP]. if (rule.Name.Stack.Peek() != "." && !currObject.Stack.GetListOfTopSymbols().Contains(rule.Name.Stack.Peek())) { return(RuleConsistentWithDerivation.RuleInconsistent); } } return(RuleConsistentWithDerivation.RuleConsistent); }
private void Predict(Column col, List <Rule> ruleList, State state, NonTerminalObject currObject) { //if (generator) //{ // var rule = Grammar.GetRandomRuleForAGivenLHS(currObject.NonTerminal, Grammar.Rules[currObject.NonTerminal]); // ruleList = new List<Rule> { rule }; //} //var preds = GenerateSetOfPredictions(); if (generator) { Rule rule = null; var l = Grammar.Rules[currObject.NonTerminal]; var feasibleRules = new List <Rule>(); //when generating, predict only rules that terminate the derivation successfully. foreach (var candidate in l) { var c = IsPredictedRuleConsistentWithCurrentDerivation(currObject, candidate); if (c == RuleConsistentWithDerivation.SkipGeneration) { return; } //temporary: do not push another symbol if the current stack already contains a symbol //in other words: allow only one symbol. var complementPositionObject = candidate.Production[candidate.ComplementPosition]; var isPushRule = !complementPositionObject.IsStackEmpty() && complementPositionObject.Stack.Top != Grammar.Epsilon; if (!currObject.IsStackEmpty() && isPushRule) { continue; } if (c == RuleConsistentWithDerivation.RuleConsistent) { feasibleRules.Add(candidate); } } if (feasibleRules.Count == 0) //no feasible rules to predict { return; } rule = Grammar.GetRandomRuleForAGivenLHS(currObject.NonTerminal, feasibleRules); ruleList = new List <Rule> { rule }; } foreach (var rule in ruleList) { if (IsPredictedRuleConsistentWithCurrentDerivation(currObject, rule) != RuleConsistentWithDerivation.RuleConsistent) { continue; } //prepare new rule based on the stack information contained in the current state //and based on the predicted rule. var createdRule = new Rule(rule); //if the rule is not a stack manipulating rule, if (rule.IsInitialRule()) { var complementPositionObject = createdRule.Production[createdRule.ComplementPosition]; //the stack of the LHS of the created rule is the stack of the current object: createdRule.Name = currObject; //copy the stack to the complement position. complementPositionObject.Stack = currObject.Stack; } else { //create left hand side of new rule. createdRule.Name.Stack = currObject.Stack; createdRule.Name.NonTerminal = currObject.NonTerminal; //create right hand side of new rule. NonTerminalStack contentOfDot; if (rule.Name.Stack.Peek() == ".") { contentOfDot = currObject.Stack; //e.g. A[..] } else { contentOfDot = currObject.Stack.GetPrefixListStackObjectOfGivenTop(rule.Name.Stack.Peek()); } //e.g A[..X] for (var i = 0; i < rule.Production.Length; i++) { var s = rule.Production[i].Stack; if (s != null) { if (s.Peek() == ".") { createdRule.Production[i].Stack = contentOfDot; // e.g, A[..] pop rule. } else if (s.PrefixList == null) { createdRule.Production[i].Stack = s; //e.g. A[X] //secondary constituent. } else { createdRule.Production[i].Stack = new NonTerminalStack(s.Peek(), contentOfDot); } //e.g. A[..X] - push rule. //calculate the new weight of the top of the stack from the weights of its sons. //if (createdRule.Production[i].Stack != null) // createdRule.Production[i].Stack.Weight = createdRule.Production[i].Stack.PrefixList != null ? createdRule.Production[i].Stack.PrefixList.Sum(x => x.Weight) : 1; } } } var newState = new State(createdRule, 0, col, null) { LogProbability = ruleLogProbabilities[rule.Number] }; if (newState.LogProbability < 0) { throw new Exception("wrong probability"); } var added = col.AddState(newState, ParsingOperation.Predict); if (Debug) { Console.WriteLine("{0} & {1} & {2} & Predicted from State {3}, added: {4}\\\\", newState.StateNumber, newState, col.Index, state.StateNumber, added); } } }
private HashSet <NonTerminalObject> GenerateSetOfPredictions(int maxElementsInStack = 2) { Queue <NonTerminalObject> queue = new Queue <NonTerminalObject>(); HashSet <NonTerminalObject> visitedNonTerminalObjects = new HashSet <NonTerminalObject>(new NonTerminalObjectStackComparer()); NonTerminalObject o = null; foreach (var moveable in Grammar.Moveables) { o = new NonTerminalObject(moveable); o.Stack = new NonTerminalStack(moveable); queue.Enqueue(o); } while (queue.Any()) { var rhs = queue.Dequeue(); visitedNonTerminalObjects.Add(rhs); var rulesforRHS = Grammar.RHSDictionary[rhs.NonTerminal].ToList(); foreach (var item in rulesforRHS) { o = null; var rule = Grammar.ruleNumberDictionary[item.Item1]; int RHSPosition = item.Item2; if (rule.Name.NonTerminal == Grammar.StartSymbol) { continue; } if (rule.IsInitialRule()) { if (rule.ComplementPosition == RHSPosition) { o = new NonTerminalObject(rule.Name.NonTerminal); o.Stack = new NonTerminalStack(rhs.Stack); if (!visitedNonTerminalObjects.Contains(o)) { queue.Enqueue(o); } } } else { NonTerminalStack contentOfDot; var s = rule.Production[RHSPosition].Stack; if (s != null) { if (s.Peek() == ".") { contentOfDot = rhs.Stack; } else if (s.PrefixList != null) { contentOfDot = rhs.Stack.GetPrefixListStackObjectOfGivenTop(rhs.Stack.Peek()); } else { continue; } //assumption: if this is a secondary constituent (i.e, s.PrefixList == null), does not participate in the sharing of stacks, //the LHS will be handled through the primary constituent (the distinguished descendant). o = new NonTerminalObject(rule.Name.NonTerminal); if (rule.Name.Stack.Peek() == ".") { if (contentOfDot != null) { o.Stack = new NonTerminalStack(contentOfDot); } } else { if (contentOfDot == null || contentOfDot.Depth() < maxElementsInStack) { o.Stack = new NonTerminalStack(rule.Name.Stack.Peek(), contentOfDot); } } if (o.Stack != null && !visitedNonTerminalObjects.Contains(o)) { queue.Enqueue(o); } } } } } return(visitedNonTerminalObjects); }