/// <summary> /// Shifting is legal as long as the state is not finished and there /// are more items on the queue to be shifted. /// </summary> /// <remarks> /// Shifting is legal as long as the state is not finished and there /// are more items on the queue to be shifted. /// TODO: go through the papers and make sure they don't mention any /// other conditions where one shouldn't shift /// </remarks> public virtual bool IsLegal(State state, IList <ParserConstraint> constraints) { if (state.finished) { return(false); } if (state.tokenPosition >= state.sentence.Count) { return(false); } // We disallow shifting when the previous transition was a right // head transition to a partial (binarized) state // TODO: I don't have an explanation for this, it was just stated // in Zhang & Clark 2009 if (state.stack.Size() > 0) { Tree top = state.stack.Peek(); // Temporary node, eg part of a binarized sequence if (top.Label().Value().StartsWith("@") && top.Children().Length == 2 && ShiftReduceUtils.GetBinarySide(top) == BinaryTransition.Side.Right) { return(false); } } if (constraints == null || state.stack.Size() == 0) { return(true); } Tree top_1 = state.stack.Peek(); // If there are ParserConstraints, you can only shift if shifting // will not make a constraint unsolvable. This happens if we // shift beyond the right end of a constraint which is not solved. foreach (ParserConstraint constraint in constraints) { // either went past or haven't gotten to this constraint yet if (ShiftReduceUtils.RightIndex(top_1) != constraint.end - 1) { continue; } int left = ShiftReduceUtils.LeftIndex(top_1); if (left < constraint.start) { continue; } if (left > constraint.start) { return(false); } if (!ShiftReduceUtils.ConstraintMatchesTreeTop(top_1, constraint)) { return(false); } } return(true); }
public virtual bool IsLegal(State state, IList <ParserConstraint> constraints) { bool legal = !state.finished && state.tokenPosition >= state.sentence.Count && state.stack.Size() == 1 && rootStates.Contains(state.stack.Peek().Value()); if (!legal || constraints == null) { return(legal); } foreach (ParserConstraint constraint in constraints) { if (constraint.start != 0 || constraint.end != state.sentence.Count) { continue; } if (!ShiftReduceUtils.ConstraintMatchesTreeTop(state.stack.Peek(), constraint)) { return(false); } } return(true); }
/// <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); }