/// <summary> /// Copy constructor. /// </summary> /// <param name="ctxt">The simple context.</param> public SimpleContext(SimpleContext ctxt) : base(ctxt) { m_featSys = ctxt.m_featSys; m_featureValues = new FeatureBundle(ctxt.m_featureValues); m_antiFeatureValues = new FeatureBundle(ctxt.m_antiFeatureValues); }
/// <summary> /// Combines this pattern with the specified pattern. This is used by phonological rules to /// generate the RHS target and by morphological rules to generate the RHS template for /// modify-from output records. The patterns must be the same size. /// </summary> /// <param name="pattern">The pattern.</param> /// <returns>The phonetic pattern which is a combination of this pattern and the specified pattern.</returns> /// <exception cref="System.ArgumentException">Thrown when the size of <c>pattern</c> does not match the size of this pattern.</exception> public PhoneticPattern Combine(PhoneticPattern pattern) { if (Count != pattern.Count) { throw new ArgumentException(HCStrings.kstidPatternCombine, "pattern"); } PhoneticPattern result = new PhoneticPattern(); PhoneticPatternNode lhsNode = pattern.First; foreach (PhoneticPatternNode rhsNode in this) { // combine the simple contexts if (rhsNode.Type == PhoneticPatternNode.NodeType.SIMP_CTXT && lhsNode.Type == PhoneticPatternNode.NodeType.SIMP_CTXT) { SimpleContext rhsCtxt = rhsNode as SimpleContext; SimpleContext lhsCtxt = lhsNode as SimpleContext; result.Add(rhsCtxt.Combine(lhsCtxt)); } lhsNode = lhsNode.GetNext(); } return(result); }
/// <summary> /// Checks for overlap of features between the specified simple context and the specified /// environment. /// </summary> /// <param name="ctxt">The simple context.</param> /// <param name="envSeq">The environment.</param> /// <returns> /// <c>true</c> if there is no overlap, otherwise <c>false</c>. /// </returns> bool IsNonSelfOpaquing(SimpleContext ctxt, PhoneticPattern env) { foreach (PhoneticPatternNode node in env) { switch (node.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext envCtxt = node as SimpleContext; if (!envCtxt.FeatureValues.IsDisjoint(ctxt.AntiFeatureValues)) { return(false); } break; case PhoneticPatternNode.NodeType.BDRY_CTXT: break; case PhoneticPatternNode.NodeType.PATTERN: NestedPhoneticPattern optSeq = node as NestedPhoneticPattern; if (!IsNonSelfOpaquing(ctxt, optSeq.Pattern)) { return(false); } break; } } return(true); }
void Untruncate(PhoneticPattern lhs, PhoneticShape output, bool optional, VariableValues instantiatedVars) { // create segments from the LHS partition pattern and append them to the output foreach (PhoneticPatternNode node in lhs) { switch (node.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext ctxt = node as SimpleContext; Segment newSeg = ctxt.UnapplyDeletion(instantiatedVars); newSeg.IsOptional = optional; output.Add(newSeg); break; case PhoneticPatternNode.NodeType.PATTERN: NestedPhoneticPattern nestedPattern = node as NestedPhoneticPattern; // untruncate nested partitions the maximum number of times it can occur, // marking any segments that occur after the minimum number of occurrences // as optional for (int j = 0; j < nestedPattern.MaxOccur; j++) { Untruncate(nestedPattern.Pattern, output, j >= nestedPattern.MinOccur, instantiatedVars); } break; case PhoneticPatternNode.NodeType.BDRY_CTXT: // skip boundaries break; } } }
protected override SimpleContext CombineFeatures(SimpleContext ctxt) { NaturalClassContext result = base.CombineFeatures(ctxt) as NaturalClassContext; if (ctxt.ContextType == SimpleContextType.NATURAL_CLASS) { NaturalClassContext ncCtxt = ctxt as NaturalClassContext; // add variables from the specified pattern's context foreach (KeyValuePair <string, bool> varPolarity in ncCtxt.m_variables) { if (!Owner.IsFeatureReferenced(m_alphaVars.GetFeature(varPolarity.Key))) { result.m_variables[varPolarity.Key] = varPolarity.Value; } } foreach (KeyValuePair <string, bool> varPolarity in ncCtxt.m_antiVariables) { if (!Owner.IsFeatureReferenced(m_alphaVars.GetFeature(varPolarity.Key))) { result.m_antiVariables[varPolarity.Key] = varPolarity.Value; } } } return(result); }
public SimpleContext Combine(SimpleContext ctxt) { if (m_featSys.HasFeatures) { return(CombineFeatures(ctxt)); } else { return(Clone() as SimpleContext); } }
/// <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; } }
bool UnapplyNarrow(PhoneticShape input) { List <Match> matches = new List <Match>(); PhoneticShapeNode node = input.First; Match match; // deletion subrules are always treated like simultaneous subrules during unapplication while (FindNextMatchRHS(node, Direction.RIGHT, out match)) { matches.Add(match); node = match.EntireMatch[0].Next; } foreach (Match m in matches) { PhoneticShapeNode cur = m.EntireMatch[m.EntireMatch.Count - 1]; foreach (PhoneticPatternNode lhsNode in m_rule.m_lhs) { if (lhsNode.Type != PhoneticPatternNode.NodeType.SIMP_CTXT) { continue; } SimpleContext ctxt = lhsNode as SimpleContext; Segment newSeg = ctxt.UnapplyDeletion(m.VariableValues); // mark the undeleted segment as optional newSeg.IsOptional = true; cur.Insert(newSeg, Direction.RIGHT); cur = newSeg; } if (m_analysisTarget.Count > 0) { foreach (PhoneticShapeNode matchNode in m.EntireMatch) { matchNode.IsOptional = true; } } } return(matches.Count > 0); }
/// <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; } } }
protected virtual SimpleContext CombineFeatures(SimpleContext ctxt) { SimpleContext result = Clone() as SimpleContext; // collect all of the possible values of the features List <FeatureValue> featVals = new List <FeatureValue>(); foreach (Feature feature in Owner.Features) { featVals.AddRange(feature.PossibleValues); } // create a mask feature bundle from all possible values FeatureBundle mask = new FeatureBundle(featVals, m_featSys); FeatureBundle temp = ctxt.FeatureValues.Clone(); // remove features referenced in the this pattern's context temp.RemoveValues(mask); // add remaining features from the specified pattern's context to this pattern's context result.FeatureValues.AddValues(temp); // remove anti features referenced in the specified pattern's context from this pattern's context result.AntiFeatureValues.RemoveValues(ctxt.AntiFeatureValues); return(result); }
/// <summary> /// Initializes a new instance of the <see cref="ModifyFromInput"/> class. /// </summary> /// <param name="partition">The partition to modify.</param> /// <param name="ctxt">The simple context.</param> /// <param name="morpher">The morpher.</param> public ModifyFromInput(int partition, SimpleContext ctxt, Morpher morpher) { m_partition = partition; m_ctxt = ctxt; m_morpher = morpher; }
/// <summary> /// Initializes a new instance of the <see cref="InsertSimpleContext"/> class. /// </summary> /// <param name="ctxt">The simple context.</param> public InsertSimpleContext(SimpleContext ctxt) { m_ctxt = ctxt; }
protected override SimpleContext CombineFeatures(SimpleContext ctxt) { NaturalClassContext result = base.CombineFeatures(ctxt) as NaturalClassContext; if (ctxt.ContextType == SimpleContextType.NATURAL_CLASS) { NaturalClassContext ncCtxt = ctxt as NaturalClassContext; // add variables from the specified pattern's context foreach (KeyValuePair<string, bool> varPolarity in ncCtxt.m_variables) { if (!Owner.IsFeatureReferenced(m_alphaVars.GetFeature(varPolarity.Key))) result.m_variables[varPolarity.Key] = varPolarity.Value; } foreach (KeyValuePair<string, bool> varPolarity in ncCtxt.m_antiVariables) { if (!Owner.IsFeatureReferenced(m_alphaVars.GetFeature(varPolarity.Key))) result.m_antiVariables[varPolarity.Key] = varPolarity.Value; } } return result; }
protected virtual SimpleContext CombineFeatures(SimpleContext ctxt) { SimpleContext result = Clone() as SimpleContext; // collect all of the possible values of the features List<FeatureValue> featVals = new List<FeatureValue>(); foreach (Feature feature in Owner.Features) featVals.AddRange(feature.PossibleValues); // create a mask feature bundle from all possible values FeatureBundle mask = new FeatureBundle(featVals, m_featSys); FeatureBundle temp = ctxt.FeatureValues.Clone(); // remove features referenced in the this pattern's context temp.RemoveValues(mask); // add remaining features from the specified pattern's context to this pattern's context result.FeatureValues.AddValues(temp); // remove anti features referenced in the specified pattern's context from this pattern's context result.AntiFeatureValues.RemoveValues(ctxt.AntiFeatureValues); return result; }
/// <summary> /// Checks for overlap of features between the specified simple context and the specified /// environment. /// </summary> /// <param name="ctxt">The simple context.</param> /// <param name="envSeq">The environment.</param> /// <returns> /// <c>true</c> if there is no overlap, otherwise <c>false</c>. /// </returns> bool IsNonSelfOpaquing(SimpleContext ctxt, PhoneticPattern env) { foreach (PhoneticPatternNode node in env) { switch (node.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: SimpleContext envCtxt = node as SimpleContext; if (!envCtxt.FeatureValues.IsDisjoint(ctxt.AntiFeatureValues)) return false; break; case PhoneticPatternNode.NodeType.BDRY_CTXT: break; case PhoneticPatternNode.NodeType.PATTERN: NestedPhoneticPattern optSeq = node as NestedPhoneticPattern; if (!IsNonSelfOpaquing(ctxt, optSeq.Pattern)) return false; break; } } return true; }
public SimpleContext Combine(SimpleContext ctxt) { if (m_featSys.HasFeatures) return CombineFeatures(ctxt); else return Clone() as SimpleContext; }