/// <summary> /// Applies the RHS to the matched segments. /// </summary> /// <param name="dir">The direction.</param> /// <param name="match">The matched segments.</param> /// <param name="instantiatedVars">The instantiated variables.</param> public void ApplyRHS(Direction dir, IList <PhoneticShapeNode> match, VariableValues instantiatedVars) { switch (Type) { case ChangeType.FEATURE: int i = 0; for (PhoneticPatternNode pseqNode = m_rhs.GetFirst(dir); pseqNode != null; pseqNode = pseqNode.GetNext(dir)) { switch (pseqNode.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext ctxt = pseqNode as SimpleContext; // match[i] should be a segment, should I check that here? while (match[i].Type == PhoneticShapeNode.NodeType.BOUNDARY) { i++; } Segment seg = match[i] as Segment; ctxt.Apply(seg, instantiatedVars); // marked the segment as altered seg.IsClean = false; break; case PhoneticPatternNode.NodeType.BDRY_CTXT: // boundaries should match, should I check that here? break; } i++; } break; case ChangeType.NARROW: ApplyInsertion(dir, match, instantiatedVars); // remove matching segments foreach (PhoneticShapeNode node in match) { node.Remove(); } break; case ChangeType.EPENTHESIS: // insert new segments or boundaries ApplyInsertion(dir, match, instantiatedVars); break; } }
/// <summary> /// Checks if the subrule will be unapplied vacuously. Vacuous unapplication means that /// the subrule will actually make changes to the phonetic shape. This is important to know /// for self-opaquing, simultaneously applying subrules, since we unapply these subrules /// until they unapply nonvacuously. /// </summary> /// <param name="match">The match.</param> /// <param name="dir">The direction.</param> /// <returns></returns> bool CheckVacuousUnapplication(Match match, Direction dir) { PhoneticPatternNode rhsNode = m_rhs.GetFirst(dir); IList <PhoneticShapeNode> nodes = match.EntireMatch; int i = 0; while (i < nodes.Count) { if (Type == ChangeType.EPENTHESIS) { // for epenthesis subrules, simply check if the epenthesized segment is // already marked as optional if (!nodes[i++].IsOptional) { return(true); } } else { switch (rhsNode.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext ctxt = rhsNode as SimpleContext; Segment seg = nodes[i] as Segment; if (ctxt.IsUnapplicationVacuous(seg, match.VariableValues)) { return(true); } i++; break; case PhoneticPatternNode.NodeType.BDRY_CTXT: break; } rhsNode = rhsNode.GetNext(dir); } } return(false); }
void UnapplyRHS(Direction dir, IList <PhoneticShapeNode> match, VariableValues instantiatedVars) { switch (Type) { case ChangeType.FEATURE: int i = 0; // if there are no phonetic features, unapply using the LHS, since we are simply replacing PhoneticPattern unappPattern = m_rule.Morpher.PhoneticFeatureSystem.HasFeatures ? m_analysisTarget : m_rule.m_lhs; for (PhoneticPatternNode pseqNode = unappPattern.GetFirst(dir); pseqNode != null; pseqNode = pseqNode.GetNext(dir)) { switch (pseqNode.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext ctxt = pseqNode as SimpleContext; // match[i] should be a segment, should I check that here? Segment seg = match[i] as Segment; ctxt.Unapply(seg, instantiatedVars); break; case PhoneticPatternNode.NodeType.BDRY_CTXT: // skip boundaries continue; } i++; } break; case ChangeType.EPENTHESIS: // do not remove epenthesized segments, since it is possible that they will not // be epenthesized during synthesis, we just mark them as optional foreach (PhoneticShapeNode node in match) { node.IsOptional = true; } break; } }
void ApplyInsertion(Direction dir, IList <PhoneticShapeNode> match, VariableValues instantiatedVars) { PhoneticShapeNode cur = match[match.Count - 1]; for (PhoneticPatternNode pseqNode = m_rhs.GetFirst(dir); pseqNode != null; pseqNode = pseqNode.GetNext(dir)) { PhoneticShapeNode newNode = null; switch (pseqNode.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext ctxt = pseqNode as SimpleContext; newNode = ctxt.ApplyInsertion(instantiatedVars); break; case PhoneticPatternNode.NodeType.BDRY_CTXT: newNode = new Boundary(pseqNode as BoundaryContext); break; } if (newNode != null) { try { cur.Insert(newNode, dir); } catch (InvalidOperationException ioe) { MorphException me = new MorphException(MorphException.MorphErrorType.TOO_MANY_SEGS, m_rule.Morpher, string.Format(HCStrings.kstidTooManySegs, m_rule.ID), ioe); me.Data["rule"] = m_rule.ID; throw me; } cur = newNode; } } }