public static void FindKnownStates(Tree tree, ICollection <string> knownStates) { if (tree.IsLeaf() || tree.IsPreTerminal()) { return; } if (!ShiftReduceUtils.IsTemporary(tree)) { knownStates.Add(tree.Value()); } foreach (Tree child in tree.Children()) { FindKnownStates(child, knownStates); } }
/// <summary>Legal as long as there are at least two items on the state's stack.</summary> public virtual bool IsLegal(State state, IList <ParserConstraint> constraints) { // some of these quotes come directly from Zhang Clark 09 if (state.finished) { return(false); } if (state.stack.Size() <= 1) { return(false); } // at least one of the two nodes on top of stack must be non-temporary if (ShiftReduceUtils.IsTemporary(state.stack.Peek()) && ShiftReduceUtils.IsTemporary(state.stack.Pop().Peek())) { return(false); } if (ShiftReduceUtils.IsTemporary(state.stack.Peek())) { if (side == BinaryTransition.Side.Left) { return(false); } if (!ShiftReduceUtils.IsEquivalentCategory(label, state.stack.Peek().Value())) { return(false); } } if (ShiftReduceUtils.IsTemporary(state.stack.Pop().Peek())) { if (side == BinaryTransition.Side.Right) { return(false); } if (!ShiftReduceUtils.IsEquivalentCategory(label, state.stack.Pop().Peek().Value())) { return(false); } } // don't allow binarized labels if it makes the state have a stack // of size 1 and a queue of size 0 if (state.stack.Size() == 2 && IsBinarized() && state.EndOfQueue()) { return(false); } // when the stack contains only two nodes, temporary resulting // nodes from binary reduce must be left-headed if (state.stack.Size() == 2 && IsBinarized() && side == BinaryTransition.Side.Right) { return(false); } // when the queue is empty and the stack contains more than two // nodes, with the third node from the top being temporary, binary // reduce can be applied only if the resulting node is non-temporary if (state.EndOfQueue() && state.stack.Size() > 2 && ShiftReduceUtils.IsTemporary(state.stack.Pop().Pop().Peek()) && IsBinarized()) { return(false); } // when the stack contains more than two nodes, with the third // node from the top being temporary, temporary resulting nodes // from binary reduce must be left-headed if (state.stack.Size() > 2 && ShiftReduceUtils.IsTemporary(state.stack.Pop().Pop().Peek()) && IsBinarized() && side == BinaryTransition.Side.Right) { return(false); } if (constraints == null) { return(true); } Tree top = state.stack.Peek(); int leftTop = ShiftReduceUtils.LeftIndex(top); int rightTop = ShiftReduceUtils.RightIndex(top); Tree next = state.stack.Pop().Peek(); int leftNext = ShiftReduceUtils.LeftIndex(next); // The binary transitions are affected by constraints in the // following two circumstances. If a transition would cross the // left boundary of a constraint, that is illegal. If the // transition is exactly the right size for the constraint and // would make a temporary node, that is also illegal. foreach (ParserConstraint constraint in constraints) { if (leftTop == constraint.start) { // can't binary reduce away from a tree which doesn't match a constraint if (rightTop == constraint.end - 1) { if (!ShiftReduceUtils.ConstraintMatchesTreeTop(top, constraint)) { return(false); } else { continue; } } else { if (rightTop >= constraint.end) { continue; } else { // can't binary reduce if it would make the tree cross the left boundary return(false); } } } // top element is further left than the constraint, so // there's no harm to be done by binary reduce if (leftTop < constraint.start) { continue; } // top element is past the end of the constraint, so it must already be satisfied if (leftTop >= constraint.end) { continue; } // now leftTop > constraint.start and < constraint.end, eg inside the constraint // the next case is no good because it crosses the boundary if (leftNext < constraint.start) { return(false); } if (leftNext > constraint.start) { continue; } // can't transition to a binarized node when there's a constraint that matches. if (rightTop == constraint.end - 1 && IsBinarized()) { return(false); } } return(true); }
/// <summary> /// Returns a transition which might not even be part of the model, /// but will hopefully allow progress in an otherwise stuck parse /// TODO: perhaps we want to create an EmergencyTransition class /// which indicates that something has gone wrong /// </summary> public virtual ITransition FindEmergencyTransition(State state, IList <ParserConstraint> constraints) { if (state.stack.Size() == 0) { return(null); } // See if there is a constraint whose boundaries match the end // points of the top node on the stack. If so, we can apply a // UnaryTransition / CompoundUnaryTransition if that would solve // the constraint if (constraints != null) { Tree top = state.stack.Peek(); foreach (ParserConstraint constraint in constraints) { if (ShiftReduceUtils.LeftIndex(top) != constraint.start || ShiftReduceUtils.RightIndex(top) != constraint.end - 1) { continue; } if (ShiftReduceUtils.ConstraintMatchesTreeTop(top, constraint)) { continue; } // found an unmatched constraint that can be fixed with a unary transition // now we need to find a matching state for the transition foreach (string label in knownStates) { if (constraint.state.Matcher(label).Matches()) { return((op.compoundUnaries) ? new CompoundUnaryTransition(Java.Util.Collections.SingletonList(label), false) : new UnaryTransition(label, false)); } } } } if (ShiftReduceUtils.IsTemporary(state.stack.Peek()) && (state.stack.Size() == 1 || ShiftReduceUtils.IsTemporary(state.stack.Pop().Peek()))) { return((op.compoundUnaries) ? new CompoundUnaryTransition(Java.Util.Collections.SingletonList(Sharpen.Runtime.Substring(state.stack.Peek().Value(), 1)), false) : new UnaryTransition(Sharpen.Runtime.Substring(state.stack.Peek().Value(), 1), false)); } if (state.stack.Size() == 1 && state.tokenPosition >= state.sentence.Count) { // either need to finalize or transition to a root state if (!rootStates.Contains(state.stack.Peek().Value())) { string root = rootStates.GetEnumerator().Current; return((op.compoundUnaries) ? new CompoundUnaryTransition(Java.Util.Collections.SingletonList(root), false) : new UnaryTransition(root, false)); } } if (state.stack.Size() == 1) { return(null); } if (ShiftReduceUtils.IsTemporary(state.stack.Peek())) { return(new BinaryTransition(Sharpen.Runtime.Substring(state.stack.Peek().Value(), 1), BinaryTransition.Side.Right)); } if (ShiftReduceUtils.IsTemporary(state.stack.Pop().Peek())) { return(new BinaryTransition(Sharpen.Runtime.Substring(state.stack.Pop().Peek().Value(), 1), BinaryTransition.Side.Left)); } return(null); }