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); } } }