/// <summary> /// Initializes a new instance of the <see cref="Subrule"/> class. /// </summary> /// <param name="rhs">The RHS.</param> /// <param name="env">The environment.</param> /// <param name="rule">The phonological rule.</param> /// <exception cref="System.ArgumentException">Thrown when the size of the RHS is greater than the /// size of the specified rule's LHS and the LHS's size is greater than 1. A standard phonological /// rule does not currently support this type of widening.</exception> public Subrule(PhoneticPattern rhs, Environment env, StandardPhonologicalRule rule) { m_rhs = rhs; m_env = env; m_rule = rule; switch (Type) { case ChangeType.NARROW: case ChangeType.EPENTHESIS: // analysis target is a copy of the RHS, because there is no LHS m_analysisTarget = m_rhs.Clone(); break; case ChangeType.WIDEN: // before generating the analysis we must extend the length of the LHS // to match the length of the RHS PhoneticPattern lhs = m_rule.m_lhs.Clone(); while (lhs.Count != m_rhs.Count) lhs.Add(lhs.First.Clone()); m_analysisTarget = m_rhs.Combine(lhs); break; case ChangeType.FEATURE: m_analysisTarget = m_rhs.Combine(m_rule.m_lhs); break; case ChangeType.UNKNOWN: throw new ArgumentException(HCStrings.kstidInvalidSubruleType, "rhs"); } }
/// <summary> /// Initializes a new instance of the <see cref="Subrule"/> class. /// </summary> /// <param name="id">The id.</param> /// <param name="desc">The description.</param> /// <param name="morpher">The morpher.</param> /// <param name="headLhs">The head LHS.</param> /// <param name="nonHeadLhs">The non-head LHS.</param> /// <param name="rhs">The RHS.</param> /// <param name="alphaVars">The alpha variables.</param> public Subrule(string id, string desc, Morpher morpher, IEnumerable<PhoneticPattern> headLhs, IEnumerable<PhoneticPattern> nonHeadLhs, IEnumerable<MorphologicalOutput> rhs, AlphaVariables alphaVars) : base (id, desc, morpher) { m_alphaVars = alphaVars; List<PhoneticPattern> lhs = new List<PhoneticPattern>(); lhs.AddRange(headLhs); lhs.AddRange(nonHeadLhs); m_transform = new MorphologicalTransform(lhs, rhs, MorphologicalTransform.RedupMorphType.IMPLICIT); // the LHS template is generated by simply concatenating all of the // LHS partitions; it matches the entire word, so we check for both the // left and right margins. m_headLhsTemp = new PhoneticPattern(); m_headLhsTemp.Add(new MarginContext(Direction.LEFT)); int partition = 0; foreach (PhoneticPattern pat in headLhs) m_headLhsTemp.AddPartition(pat, partition++); m_headLhsTemp.Add(new MarginContext(Direction.RIGHT)); m_firstNonHeadPartition = partition; m_nonHeadLhsTemp = new PhoneticPattern(); m_nonHeadLhsTemp.Add(new MarginContext(Direction.LEFT)); foreach (PhoneticPattern pat in nonHeadLhs) m_nonHeadLhsTemp.AddPartition(pat, partition++); m_nonHeadLhsTemp.Add(new MarginContext(Direction.RIGHT)); }
/// <summary> /// Initializes a new instance of the <see cref="Subrule"/> class. /// </summary> /// <param name="id">The id.</param> /// <param name="desc">The description.</param> /// <param name="morpher">The morpher.</param> /// <param name="lhs">The LHS.</param> /// <param name="rhs">The RHS.</param> /// <param name="alphaVars">The alpha variables.</param> /// <param name="redupMorphType">The full reduplication type.</param> public Subrule(string id, string desc, Morpher morpher, IEnumerable<PhoneticPattern> lhs, IEnumerable<MorphologicalOutput> rhs, AlphaVariables alphaVars, MorphologicalTransform.RedupMorphType redupMorphType) : base (id, desc, morpher) { m_alphaVars = alphaVars; m_transform = new MorphologicalTransform(lhs, rhs, redupMorphType); // the LHS template is generated by simply concatenating all of the // LHS partitions; it matches the entire word, so we check for both the // left and right margins. m_lhsTemp = new PhoneticPattern(); m_lhsTemp.Add(new MarginContext(Direction.LEFT)); int partition = 0; foreach (PhoneticPattern pat in lhs) { m_lhsTemp.AddPartition(pat, partition, m_transform.IsGreedy(partition)); partition++; } m_lhsTemp.Add(new MarginContext(Direction.RIGHT)); }
/// <summary> /// Initializes a new instance of the <see cref="MorphologicalTransform"/> class. /// </summary> /// <param name="lhs">The LHS.</param> /// <param name="rhs">The RHS.</param> public MorphologicalTransform(IEnumerable<PhoneticPattern> lhs, IEnumerable<MorphologicalOutput> rhs, RedupMorphType redupMorphType) { m_lhs = new List<PhoneticPattern>(lhs); m_rhs = new List<MorphologicalOutput>(rhs); m_modifyFromCtxts = new Dictionary<int, SimpleContext>(); // reduplication flags for each morphological output record CheckReduplication(redupMorphType); m_rhsTemp = new PhoneticPattern(); m_modifyFromCtxts = new Dictionary<int, SimpleContext>(); m_rhsTemp.Add(new MarginContext(Direction.LEFT)); for (int i = 0; i < m_rhs.Count; i++) m_rhs[i].GenerateRHSTemplate(m_rhsTemp, m_lhs, m_modifyFromCtxts); m_rhsTemp.Add(new MarginContext(Direction.RIGHT)); }
/// <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; }
bool ProcessIterative(PhoneticShape input, Direction dir, PhoneticPattern ptemp, ModeType mode) { bool reordered = false; PhoneticShapeNode node = input.GetFirst(dir); Match match; // iterate thru each match while (FindNextMatch(node, dir, ptemp, mode, out match)) { // reorder the matching segments Reorder(dir, match); reordered = true; IList<PhoneticShapeNode> nodes = match.EntireMatch; node = nodes[nodes.Count - 1].GetNext(dir); } return reordered; }
bool FindNextMatch(PhoneticShapeNode node, Direction dir, PhoneticPattern ptemp, ModeType mode, out Match match) { for (; node != node.Owner.GetLast(dir); node = node.GetNext(dir)) { if (mode == ModeType.ANALYSIS && node.Type == PhoneticShapeNode.NodeType.BOUNDARY) continue; IList<Match> matches; if (ptemp.IsMatch(node, dir, mode, out matches)) { match = matches[0]; return true; } } match = null; return false; }
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; } } }
/// <summary> /// Generates the RHS template of a morphological rule. /// </summary> /// <param name="rhsTemp">The RHS template.</param> /// <param name="lhs">The LHS.</param> /// <param name="modifyFromCtxts">The modify-from contexts.</param> /// <param name="redup">The reduplication flag.</param> public override void GenerateRHSTemplate(PhoneticPattern rhsTemp, IList<PhoneticPattern> lhs, IDictionary<int, SimpleContext> modifyFromCtxts) { // copy LHS partition over the RHS, only indicate the partition if this is // the first time this partition is being copied rhsTemp.AddPartition(lhs[m_partition], m_redup ? -1 : m_partition); }
public void Reset() { m_multApplication = MultAppOrder.LR_ITERATIVE; m_alphaVars = null; m_lhs = null; m_subrules.Clear(); }
void LoadPSeq(PhoneticPattern pattern, XmlElement pseqNode, AlphaVariables alphaVars, Dictionary<string, string> varFeatIds, Dictionary<string, int> partIds) { if (pseqNode == null) return; foreach (XmlNode recNode in pseqNode.ChildNodes) { if (recNode.NodeType != XmlNodeType.Element) continue; XmlElement recElem = recNode as XmlElement; IEnumerable<PhoneticPatternNode> nodes = null; switch (recElem.Name) { case "SimpleContext": nodes = LoadNatClassCtxtPSeq(recElem, alphaVars, varFeatIds); break; case "BoundaryMarker": nodes = LoadBdryCtxt(recElem); break; case "Segment": nodes = LoadSegCtxt(recElem); break; case "OptionalSegmentSequence": nodes = LoadOptSeq(recElem, alphaVars, varFeatIds, pattern.IsTarget); break; case "Segments": nodes = LoadSegCtxts(recElem); break; } int partition = -1; string id = recElem.GetAttribute("id"); if (partIds != null && !string.IsNullOrEmpty(id)) partition = partIds[id]; pattern.AddPartition(nodes, partition); } }
PhoneticPattern GenerateChangePartition(PhoneticPattern lhs, PhoneticPattern rhs) { PhoneticPattern result = new PhoneticPattern(); foreach (PhoneticPatternNode node in lhs) { switch (node.Type) { case PhoneticPatternNode.NodeType.SIMP_CTXT: PhoneticPattern temp = new PhoneticPattern(); temp.Add(node.Clone()); // generates the RHS template the same way that phonological rules generate their // RHS analysis targets result.AddMany(rhs.Combine(temp)); break; case PhoneticPatternNode.NodeType.PATTERN: NestedPhoneticPattern nestedPattern = node as NestedPhoneticPattern; PhoneticPattern pattern = GenerateChangePartition(nestedPattern.Pattern, rhs); NestedPhoneticPattern newNestedPattern = new NestedPhoneticPattern(pattern, nestedPattern.MinOccur, nestedPattern.MaxOccur); result.Add(newNestedPattern); break; } } return result; }
/// <summary> /// Generates the RHS template. /// </summary> /// <param name="rhsTemp">The RHS template.</param> /// <param name="lhs">The LHS.</param> /// <param name="modifyFromCtxts">The modify-from contexts.</param> /// <param name="redup">The reduplication flag.</param> public override void GenerateRHSTemplate(PhoneticPattern rhsTemp, IList<PhoneticPattern> lhs, IDictionary<int, SimpleContext> modifyFromCtxts) { for (PhoneticShapeNode node = m_pshape.Begin; node != m_pshape.Last; node = node.Next) { // create contexts from the segments and boundaries in the phonetic shape // and append them to the RHS template switch (node.Type) { case PhoneticShapeNode.NodeType.SEGMENT: rhsTemp.Add(new SegmentContext(node as Segment)); break; case PhoneticShapeNode.NodeType.BOUNDARY: rhsTemp.Add(new BoundaryContext(node as Boundary)); break; } } }
/// <summary> /// Generates the RHS template of a morphological rule. /// </summary> /// <param name="rhsTemp">The RHS template.</param> /// <param name="lhs">The LHS.</param> /// <param name="modifyFromCtxts">The modify-from contexts.</param> /// <param name="redup">The reduplication flag.</param> public override void GenerateRHSTemplate(PhoneticPattern rhsTemp, IList<PhoneticPattern> lhs, IDictionary<int, SimpleContext> modifyFromCtxts) { PhoneticPattern ctxtPattern = new PhoneticPattern(); ctxtPattern.Add(m_ctxt); // combines the simple context with all of the simple contexts on the LHS // and adds the results to the RHS template PhoneticPattern pattern = GenerateChangePartition(lhs[m_partition], ctxtPattern); rhsTemp.AddPartition(pattern, m_redup ? -1 : m_partition); // add context to the modify-from contexts modifyFromCtxts[m_partition] = m_ctxt; }
/// <summary> /// Generates the RHS template of a morphological rule. /// </summary> /// <param name="rhsTemp">The RHS template.</param> /// <param name="lhs">The LHS.</param> /// <param name="modifyFromCtxts">The modify-from contexts.</param> /// <param name="redup">The reduplication flag.</param> public override void GenerateRHSTemplate(PhoneticPattern rhsTemp, IList<PhoneticPattern> lhs, IDictionary<int, SimpleContext> modifyFromCtxts) { rhsTemp.Add(m_ctxt.Clone()); }
void LoadPSubrule(XmlElement psubruleNode, StandardPhonologicalRule prule, Dictionary<string, string> varFeatIds) { XmlElement structElem = psubruleNode.SelectSingleNode("PhonologicalSubruleStructure[@isActive='yes']") as XmlElement; PhoneticPattern rhs = new PhoneticPattern(true); LoadPSeq(rhs, structElem.SelectSingleNode("PhoneticOutput/PhoneticSequence") as XmlElement, prule.AlphaVariables, varFeatIds, null); Environment env = LoadEnv(structElem.SelectSingleNode("Environment"), prule.AlphaVariables, varFeatIds); StandardPhonologicalRule.Subrule sr = null; try { sr = new StandardPhonologicalRule.Subrule(rhs, env, prule); } catch (ArgumentException ae) { LoadException le = new LoadException(LoadException.LoadErrorType.INVALID_SUBRULE_TYPE, this, HCStrings.kstidInvalidSubruleType, ae); le.Data["rule"] = prule.ID; throw le; } sr.RequiredPOSs = LoadPOSs(psubruleNode.GetAttribute("requiredPartsOfSpeech")); sr.RequiredMPRFeatures = LoadMPRFeatures(psubruleNode.GetAttribute("requiredMPRFeatures")); sr.ExcludedMPRFeatures = LoadMPRFeatures(psubruleNode.GetAttribute("excludedMPRFeatures")); prule.AddSubrule(sr); }
PhoneticPattern LoadPTemp(XmlElement ptempNode, AlphaVariables varFeats, Dictionary<string, string> varFeatIds, Dictionary<string, int> partIds) { if (ptempNode == null) return null; bool initial = ptempNode.GetAttribute("initialBoundaryCondition") == "true"; bool final = ptempNode.GetAttribute("finalBoundaryCondition") == "true"; PhoneticPattern pattern = new PhoneticPattern(); if (initial) pattern.Add(new MarginContext(Direction.LEFT)); LoadPSeq(pattern, ptempNode.SelectSingleNode("PhoneticSequence") as XmlElement, varFeats, varFeatIds, partIds); if (final) pattern.Add(new MarginContext(Direction.RIGHT)); return pattern; }
IEnumerable<PhoneticPatternNode> LoadOptSeq(XmlElement optSeqNode, AlphaVariables varFeats, Dictionary<string, string> varFeatIds, bool isTarget) { string minStr = optSeqNode.GetAttribute("min"); int min = string.IsNullOrEmpty(minStr) ? 0 : Convert.ToInt32(minStr); string maxStr = optSeqNode.GetAttribute("max"); int max = string.IsNullOrEmpty(maxStr) ? -1 : Convert.ToInt32(maxStr); PhoneticPattern pattern = new PhoneticPattern(isTarget); LoadPSeq(pattern, optSeqNode, varFeats, varFeatIds, null); yield return new NestedPhoneticPattern(pattern, min, max); }
/// <summary> /// Generates the RHS template of a morphological rule. If the record /// modifies the input using a simple context, it should add that context /// to varFeats of modify-from contexts. It is used during unapplication. /// The reduplication flags are used to indicate that the same input partition /// is being copied multiple times. /// </summary> /// <param name="rhsTemp">The RHS template.</param> /// <param name="lhs">The LHS.</param> /// <param name="modifyFromCtxts">The modify-from contexts.</param> /// <param name="redup">The reduplication flag.</param> public abstract void GenerateRHSTemplate(PhoneticPattern rhsTemp, IList<PhoneticPattern> lhs, IDictionary<int, SimpleContext> modifyFromCtxts);
List<PhoneticPattern> LoadReqPhoneticInput(XmlNode reqPhonInputNode, int partition, AlphaVariables varFeats, Dictionary<string, string> varFeatIds, Dictionary<string, int> partIds) { List<PhoneticPattern> lhsList = new List<PhoneticPattern>(); XmlNodeList pseqList = reqPhonInputNode.SelectNodes("PhoneticSequence"); foreach (XmlNode pseqNode in pseqList) { XmlElement pseqElem = pseqNode as XmlElement; PhoneticPattern pattern = new PhoneticPattern(); LoadPSeq(pattern, pseqElem, varFeats, varFeatIds, null); lhsList.Add(pattern); partIds[pseqElem.GetAttribute("id")] = partition++; } return lhsList; }