protected IList <Match> MatchNext(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars) { PhoneticPatternNode n = GetNext(dir); // skip boundaries in analysis mode if (mode == ModeType.ANALYSIS) { while (n != null && n.Type == NodeType.BDRY_CTXT) { n = n.GetNext(dir); } } List <Match> matches = new List <Match>(); if (n == null) { // we are at the end of the pattern, so we have a match matches.Add(new Match(instantiatedVars)); } else { // try skipping over optional shape nodes do { // try the next node in the pattern node = node.GetNext(dir); matches.AddRange(n.Match(node, dir, mode, instantiatedVars)); }while (node != null && node.IsOptional); } return(matches); }
void ApplyIterative(PhoneticShape input, Direction dir, List <Subrule> subrules) { Match match; PhoneticShapeNode node = input.GetFirst(dir); // iterate thru each LHS match while (FindNextMatchLHS(node, dir, out match)) { IList <PhoneticShapeNode> nodes = match.EntireMatch; VariableValues instantiatedVars = match.VariableValues; bool matched = false; // check each subrule's environment foreach (Subrule sr in subrules) { if (m_lhs.Count == 0 ? sr.MatchEnvEmpty(nodes[0], dir, ModeType.SYNTHESIS, instantiatedVars) : sr.MatchEnvNonempty(nodes, dir, ModeType.SYNTHESIS, instantiatedVars)) { sr.ApplyRHS(dir, nodes, instantiatedVars); matched = true; break; } } if (matched) { node = nodes[nodes.Count - 1].GetNext(dir); } else { node = nodes[0].GetNext(dir); } } }
bool FindNextMatchLHS(PhoneticShapeNode node, Direction dir, out Match match) { for (; node != node.Owner.GetLast(dir); node = node.GetNext(dir)) { VariableValues instantiatedVars = new VariableValues(m_alphaVars); if (m_lhs.Count == 0) { // epenthesis rules always match the LHS match = new Match(instantiatedVars); match.Add(node); return(true); } else { IList <Match> matches; if (m_lhs.IsMatch(node, dir, ModeType.SYNTHESIS, instantiatedVars, out matches)) { match = matches[0]; return(true); } } } match = null; return(false); }
bool MatchAnalysisTarget(PhoneticShapeNode node, Direction dir, out Match match) { // check analysis target IList <Match> matches; VariableValues instantiatedVars = new VariableValues(m_rule.m_alphaVars); if (!m_analysisTarget.IsMatch(node, dir, ModeType.ANALYSIS, instantiatedVars, out matches)) { match = null; return(false); } match = matches[0]; // check vacuous unapplication // even if the subrule matches, we do not want to successfully unapply if no real changes are // going to be made to the phonetic shape if (!CheckVacuousUnapplication(match, dir)) { match = null; return(false); } // finally, check environment if (!MatchEnvNonempty(match.EntireMatch, dir, ModeType.ANALYSIS, match.VariableValues)) { match = null; return(false); } return(true); }
void ApplySimultaneous(PhoneticShape input, List <Subrule> subrules) { foreach (Subrule sr in subrules) { // first find all segments which match the LHS List <Match> matches = new List <Match>(); PhoneticShapeNode node = input.First; Match match; while (FindNextMatchLHS(node, Direction.RIGHT, out match)) { // check each candidate match against the subrule's environment IList <PhoneticShapeNode> nodes = match.EntireMatch; VariableValues instantiatedVars = match.VariableValues; if (m_lhs.Count == 0 ? sr.MatchEnvEmpty(nodes[0], Direction.RIGHT, ModeType.SYNTHESIS, instantiatedVars) : sr.MatchEnvNonempty(nodes, Direction.RIGHT, ModeType.SYNTHESIS, instantiatedVars)) { matches.Add(match); node = nodes[nodes.Count - 1].Next; } else { node = nodes[0].Next; } } // then apply changes foreach (Match m in matches) { sr.ApplyRHS(Direction.RIGHT, m.EntireMatch, m.VariableValues); } } }
public bool MatchEnvNonempty(IList <PhoneticShapeNode> match, Direction dir, ModeType mode, VariableValues instantiatedVars) { PhoneticShapeNode leftNode = null; PhoneticShapeNode rightNode = null; switch (dir) { case Direction.LEFT: rightNode = match[0].GetNext(Direction.RIGHT); leftNode = match[match.Count - 1].GetNext(Direction.LEFT); break; case Direction.RIGHT: rightNode = match[match.Count - 1].GetNext(Direction.RIGHT); leftNode = match[0].GetNext(Direction.LEFT); break; } if (!m_env.IsMatch(leftNode, rightNode, mode, instantiatedVars)) { return(false); } return(true); }
/// <summary> /// Applies the simple context to the input partition and copies it over to the output /// phonetic shape. /// </summary> /// <param name="match">The match.</param> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word synthesis.</param> /// <param name="morpheme">The morpheme info.</param> public override void Apply(Match match, WordSynthesis input, WordSynthesis output, Allomorph allomorph) { IList <PhoneticShapeNode> nodes = match.GetPartition(m_partition); if (nodes != null && nodes.Count > 0) { Morph morph = null; if (allomorph != null) { morph = new Morph(allomorph); output.Morphs.Add(morph); } for (PhoneticShapeNode node = nodes[0]; node != nodes[nodes.Count - 1].Next; node = node.Next) { PhoneticShapeNode newNode = node.Clone(); if (node.Type == PhoneticShapeNode.NodeType.SEGMENT) { Segment seg = newNode as Segment; // sets the context's features on the segment m_ctxt.Apply(seg, match.VariableValues); seg.IsClean = false; seg.Partition = morph == null ? -1 : morph.Partition; } if (morph != null) { morph.Shape.Add(newNode.Clone()); } output.Shape.Add(newNode); } } }
bool FindNextMatchRHS(PhoneticShapeNode node, Direction dir, out Match match) { for (; node != node.Owner.GetLast(dir); node = node.GetNext(dir)) { if (node.Type == PhoneticShapeNode.NodeType.BOUNDARY) { continue; } if (m_analysisTarget.Count == 0) { // if the analysis target is empty (deletion rule), // just check environment VariableValues instantiatedVars = new VariableValues(m_rule.m_alphaVars); if (MatchEnvEmpty(node, dir, ModeType.ANALYSIS, instantiatedVars)) { match = new Match(instantiatedVars); match.Add(node); return(true); } } else { // analysis target is non-empty, check everything if (MatchAnalysisTarget(node, dir, out match)) { return(true); } } } match = null; return(false); }
/// <summary> /// Checks if the specified phonetic shape matches this environment. /// </summary> /// <param name="leftNode">The left node.</param> /// <param name="rightNode">The right node.</param> /// <param name="mode">The mode.</param> /// <param name="instantiatedVars">The instantiated variables.</param> /// <returns> /// <c>true</c> if the shape successfully matched this pattern, otherwise <c>false</c>. /// </returns> public bool IsMatch(PhoneticShapeNode leftNode, PhoneticShapeNode rightNode, ModeType mode, VariableValues instantiatedVars) { VariableValues temp = instantiatedVars.Clone(); // right environment if (m_rightEnv != null) { IList <Match> matches; if (m_rightEnv.IsMatch(rightNode, Direction.RIGHT, mode, temp, out matches)) { temp.ReplaceValues(matches[0].VariableValues); } else { return(false); } } // left environment if (m_leftEnv != null) { IList <Match> matches; if (m_leftEnv.IsMatch(leftNode, Direction.LEFT, mode, temp, out matches)) { temp.ReplaceValues(matches[0].VariableValues); } else { return(false); } } instantiatedVars.ReplaceValues(temp); return(true); }
public void Add(PhoneticShapeNode node, T value, Direction dir) { switch (node.Type) { case PhoneticShapeNode.NodeType.MARGIN: if (node == node.Owner.GetLast(dir)) { // we are at the end of the phonetic shape, so add the lexical // entry to this node m_values.Add(value); return; } else { // skip first margin Add(node.GetNext(dir), value, dir); } break; case PhoneticShapeNode.NodeType.BOUNDARY: // skip boundaries Add(node.GetNext(dir), value, dir); break; case PhoneticShapeNode.NodeType.SEGMENT: Segment seg = (Segment)node; TrieNode tnode = null; foreach (TrieNode child in m_children) { if (seg.FeatureValues.FeatureSystem.HasFeatures) { // we check for exact matches of feature sets when adding if (child.m_segDef.SynthFeatures.Equals(seg.FeatureValues)) { tnode = child; break; } } else if (child.m_segDef == seg.SegmentDefinition) { tnode = child; break; } } if (tnode == null) { // new node needs to be added tnode = new TrieNode(seg.SegmentDefinition); m_children.Add(tnode); } // recursive call matching child node tnode.Add(node.GetNext(dir), value, dir); break; } }
/// <summary> /// Adds the specified phonetic shape node to the specified partition. /// </summary> /// <param name="seg">The phonetic shape node.</param> /// <param name="partition">The partition.</param> internal void Add(PhoneticShapeNode node, int partition) { if (partition >= 0) { List <PhoneticShapeNode> nodes = GetNodes(partition); nodes.Insert(0, node); } m_entireMatch.Insert(0, node); }
/// <summary> /// Checks if the specified phonetic shape node matches this boundary context. /// </summary> /// <param name="node">The phonetic shape node.</param> /// <param name="dir">The direction.</param> /// <param name="mode">The mode.</param> /// <param name="instantiatedVars">The instantiated variables.</param> /// <returns>All matches.</returns> internal override IList <Match> Match(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars) { // only match boundaries in synthesis mode if (mode == ModeType.SYNTHESIS) { switch (node.Type) { case PhoneticShapeNode.NodeType.BOUNDARY: Boundary bdry = node as Boundary; // check if string representations match if (m_bdryDef.StrRep != bdry.BoundaryDefinition.StrRep) { return(new List <Match>()); } // move to next node IList <Match> matches = MatchNext(node, dir, mode, instantiatedVars); foreach (Match match in matches) { match.Add(node, m_partition); } return(matches); case PhoneticShapeNode.NodeType.MARGIN: Margin margin = node as Margin; if (dir == margin.MarginType) { // we are at the end of the phonetic shape, so it does not match return(new List <Match>()); } else { return(Match(node.GetNext(dir), dir, mode, instantiatedVars)); } } return(new List <Match>()); } else { PhoneticPatternNode n = GetNext(dir); if (n == null) { // this was the last node in the pattern, so we have a match List <Match> matches = new List <Match>(); matches.Add(new Match(instantiatedVars)); return(matches); } else { return(n.Match(node, dir, mode, instantiatedVars)); } } }
void Reorder(Direction dir, Match match) { if (match.EntireMatch.Count == 0) { return; } PhoneticShapeNode first = null; PhoneticShapeNode last = null; switch (dir) { case Direction.RIGHT: first = match.EntireMatch[0]; last = match.EntireMatch[match.EntireMatch.Count - 1]; break; case Direction.LEFT: first = match.EntireMatch[match.EntireMatch.Count - 1]; last = match.EntireMatch[0]; break; } // remove the matching segments, so that we can reinsert them in the // new order PhoneticShapeNode cur = first.Prev; for (PhoneticShapeNode node = first; node != last.Next; node = node.Next) { node.Remove(); } // reinsert the segments in the new order for (int i = 0; i < m_lhsTemp.Count; i++) { IList <PhoneticShapeNode> partNodes = match.GetPartition(i); if (partNodes == null) { continue; } IEnumerable <PhoneticShapeNode> partEnum = dir == Direction.RIGHT ? partNodes : ReverseNodes(partNodes); foreach (PhoneticShapeNode node in partEnum) { cur.Insert(node, Direction.RIGHT); cur = node; } } }
/// <summary> /// Checks if the specified phonetic shape node matches this margin context. /// </summary> /// <param name="node">The phonetic shape node.</param> /// <param name="dir">The direction.</param> /// <param name="mode">The mode.</param> /// <param name="instantiatedVars">The instantiated variables.</param> /// <returns>All matches.</returns> internal override IList <Match> Match(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars) { if (node.Type == PhoneticShapeNode.NodeType.MARGIN) { Margin margin = node as Margin; if (m_marginType != margin.MarginType) { return(new List <Match>()); } // move to next node return(MatchNext(node, dir, mode, instantiatedVars)); } return(new List <Match>()); }
public bool MatchEnvEmpty(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars) { PhoneticShapeNode leftNode = null; PhoneticShapeNode rightNode = null; switch (dir) { case Direction.LEFT: rightNode = node; leftNode = node.GetNext(Direction.LEFT); break; case Direction.RIGHT: rightNode = node.GetNext(Direction.RIGHT); leftNode = node; break; } // in case this is an epenthesis rule, we want to ensure that the segment to the right // of where we're going to do the epenthesis is not a boundary marker, unless the // environment calls for one. if (mode == ModeType.SYNTHESIS && m_env.RightEnvironment != null && m_env.RightEnvironment.Count > 0) { if (rightNode.Type == PhoneticShapeNode.NodeType.BOUNDARY && m_env.RightEnvironment.First.Type != PhoneticPatternNode.NodeType.BDRY_CTXT) { return(false); } } // there is a small difference between legacy HC and HC.NET in matching environments when the // analysis target is empty and one of the environments is empty. In this case, legacy HC does // not try to skip the initial optional segments when matching the right environment. I think // this will cause HC.NET to overproduce a little more during analysis, which isn't that big of a // deal if (!m_env.IsMatch(leftNode, rightNode, mode, instantiatedVars)) { return(false); } // remove ambiguous variables instantiatedVars.RemoveAmbiguousVariables(); return(true); }
bool UnapplyIterative(PhoneticShape input, Direction dir) { bool unapplied = false; PhoneticShapeNode node = input.GetFirst(dir); Match match; // iterate thru all matches while (FindNextMatchRHS(node, dir, out match)) { // unapply the subrule IList <PhoneticShapeNode> nodes = match.EntireMatch; UnapplyRHS(dir, nodes, match.VariableValues); unapplied = true; node = nodes[nodes.Count - 1].GetNext(dir); } return(unapplied); }
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); }
/// <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> /// Copies a partition from the input phonetic shape to the output phonetic shape. /// </summary> /// <param name="match">The match.</param> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word synthesis.</param> /// <param name="morpheme">The morpheme info.</param> public override void Apply(Match match, WordSynthesis input, WordSynthesis output, Allomorph allomorph) { IList <PhoneticShapeNode> nodes = match.GetPartition(m_partition); if (nodes != null && nodes.Count > 0) { Morph morph = null; for (PhoneticShapeNode node = nodes[0]; node != nodes[nodes.Count - 1].Next; node = node.Next) { PhoneticShapeNode newNode = node.Clone(); // mark the reduplicated segments with the gloss partition if (m_redup) { if (allomorph != null) { if (morph == null) { morph = new Morph(allomorph); output.Morphs.Add(morph); } newNode.Partition = morph.Partition; morph.Shape.Add(node.Clone()); } else { newNode.Partition = -1; } } else if (node.Partition != -1) { if (morph == null || morph.Partition != node.Partition) { morph = input.Morphs[node.Partition].Clone(); morph.Shape.Clear(); output.Morphs.Add(morph); } newNode.Partition = morph.Partition; morph.Shape.Add(node.Clone()); } output.Shape.Add(newNode); } } }
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 a phonetic shape matches this pattern starting at the specified node. /// </summary> /// <param name="node">The phonetic shape node.</param> /// <param name="dir">The direction.</param> /// <param name="mode">The mode.</param> /// <param name="instantiatedVars">The instantiated variables.</param> /// <param name="matches">The matches.</param> /// <returns><c>true</c> if the shape successfully matched this pattern, otherwise <c>false</c></returns> public bool IsMatch(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars, out IList <Match> matches) { List <Match> matchesList = new List <Match>(); matches = matchesList; PhoneticPatternNode n = GetFirst(dir); // skip boundaries during analysis if (mode == ModeType.ANALYSIS) { while (n != null && n.Type == PhoneticPatternNode.NodeType.BDRY_CTXT) { n = n.GetNext(dir); } } if (n == null) { // we are at the end of the pattern, so it is a match matchesList.Add(new Match(instantiatedVars)); } else { PhoneticShapeNode cur = node; PhoneticShapeNode prev = null; do { matchesList.AddRange(n.Match(cur, dir, mode, instantiatedVars)); prev = cur; if (cur != null) { cur = cur.GetNext(dir); } }while (cur != null && prev.IsOptional); } //matchesList.Sort(); return(matchesList.Count > 0); }
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); }
/// <summary> /// Converts the specified string to a phonetic shape. It matches the longest possible segment /// first. /// </summary> /// <param name="str">The string.</param> /// <param name="mode">The mode.</param> /// <returns>The phonetic shape, <c>null</c> if the string contains invalid segments.</returns> public PhoneticShape ToPhoneticShape(string str, ModeType mode) { PhoneticShape ps = new PhoneticShape(); int i = 0; ps.Add(new Margin(Direction.LEFT)); while (i < str.Length) { bool match = false; for (int j = str.Length - i; j > 0; j--) { string s = str.Substring(i, j); PhoneticShapeNode node = GetPhoneticShapeNode(s, mode); if (node != null) { try { ps.Add(node); } catch (InvalidOperationException) { return(null); } i += j; match = true; break; } } if (!match) { return(null); } } ps.Add(new Margin(Direction.RIGHT)); return(ps); }
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; } } }
/// <summary> /// Inserts the segments and boundaries in to the output phonetic shape. /// </summary> /// <param name="match">The match.</param> /// <param name="input">The input word synthesis.</param> /// <param name="output">The output word synthesis.</param> /// <param name="morpheme">The morpheme info.</param> public override void Apply(Match match, WordSynthesis input, WordSynthesis output, Allomorph allomorph) { Morph morph = null; if (allomorph != null) { morph = new Morph(allomorph); output.Morphs.Add(morph); } for (PhoneticShapeNode node = m_pshape.Begin; node != m_pshape.Last; node = node.Next) { PhoneticShapeNode newNode = node.Clone(); if (morph != null) { newNode.Partition = morph.Partition; morph.Shape.Add(node.Clone()); } else { newNode.Partition = -1; } output.Shape.Add(newNode); } }
PhoneticShapeNode GetPhoneticShapeNode(string strRep, ModeType mode) { PhoneticShapeNode node = null; SegmentDefinition segDef = GetSegmentDefinition(strRep); if (segDef != null) { Segment seg = new Segment(segDef, mode == ModeType.SYNTHESIS ? segDef.SynthFeatures.Clone() : segDef.AnalysisFeatures.Clone()); if (!Morpher.PhoneticFeatureSystem.HasFeatures) { seg.InstantiateSegment(segDef); } node = seg; } else { BoundaryDefinition bdryDef = GetBoundaryDefinition(strRep); if (bdryDef != null) { node = new Boundary(bdryDef); } } return(node); }
/// <summary> /// Checks if the specified phonetic shape node matches this nested phonetic pattern. /// </summary> /// <param name="node">The phonetic shape node.</param> /// <param name="dir">The direction.</param> /// <param name="mode">The mode.</param> /// <param name="instantiatedVars">The instantiated variables.</param> /// <returns>All matches.</returns> internal override IList <Match> Match(PhoneticShapeNode node, Direction dir, ModeType mode, VariableValues instantiatedVars) { Set <Match> candidates = new Set <Match>(new MatchComparer()); Queue <KeyValuePair <Match, int> > queue = new Queue <KeyValuePair <Match, int> >(); IList <Match> firstMatches; // collect first set of matches and add them to the queue m_pattern.IsMatch(node, dir, mode, instantiatedVars, out firstMatches); foreach (Match match in firstMatches) { if (match.EntireMatch.Count == 0) { continue; } // only add it to the list of candidates if it long enough if (m_minOccur <= 1) { if (!candidates.Contains(match)) { candidates.Add(match); queue.Enqueue(new KeyValuePair <Match, int>(match, 1)); } } else { queue.Enqueue(new KeyValuePair <Match, int>(match, 1)); } } while (queue.Count > 0) { KeyValuePair <Match, int> pair = queue.Dequeue(); // if we hit upper limit then do not process this match any longer if (m_maxOccur > -1 && pair.Value >= m_maxOccur) { continue; } IList <PhoneticShapeNode> nodes = pair.Key.EntireMatch; PhoneticShapeNode n = nodes[nodes.Count - 1].GetNext(dir); IList <Match> curMatches; m_pattern.IsMatch(n, dir, mode, pair.Key.VariableValues, out curMatches); foreach (Match match in curMatches) { if (match.EntireMatch.Count == 0) { continue; } for (PhoneticShapeNode curNode = nodes[nodes.Count - 1]; curNode != nodes[0].GetPrev(dir); curNode = curNode.GetPrev(dir)) { match.Add(curNode); } // only add to the list of candidates if it is long enough if (m_minOccur <= pair.Value + 1) { if (!candidates.Contains(match)) { candidates.Add(match); queue.Enqueue(new KeyValuePair <Match, int>(match, pair.Value + 1)); } } else { queue.Enqueue(new KeyValuePair <Match, int>(match, pair.Value + 1)); } } } // iterate thru list of candidates and see if they match the rest of the pattern List <Match> matches = new List <Match>(); foreach (Match candidate in candidates) { IList <PhoneticShapeNode> nodes = candidate.EntireMatch; IList <Match> curMatches = MatchNext(nodes[nodes.Count - 1], dir, mode, candidate.VariableValues); foreach (Match match in curMatches) { for (PhoneticShapeNode curNode = nodes[nodes.Count - 1]; curNode != nodes[0].GetPrev(dir); curNode = curNode.GetPrev(dir)) { match.Add(curNode, m_partition); } matches.Add(match); } } // finally, if this pattern can occur 0 times, then collect any 0 length matches if (m_minOccur == 0) { PhoneticPatternNode n = GetNext(dir); if (n == null) { matches.Add(new Match(instantiatedVars)); } else { matches.AddRange(n.Match(node, dir, mode, instantiatedVars)); } } matches.Sort(); return(matches); }
public void AddNode(PhoneticShapeNode node) { m_nodes.Insert(0, node); }
public IList <Match> Search(PhoneticShapeNode node, Direction dir, bool partialMatch) { IList <Match> matches = null; switch (node.Type) { case PhoneticShapeNode.NodeType.MARGIN: if (node == node.Owner.GetLast(dir)) { matches = new List <Match>(); if (!partialMatch) { // we are at the end of the phonetic shape, so return // all values in this node foreach (T value in m_values) { matches.Add(new Match(value)); } } } else { // skip the first margin matches = Search(node.GetNext(dir), dir, partialMatch); } break; case PhoneticShapeNode.NodeType.BOUNDARY: // skip boundaries matches = Search(node.GetNext(dir), dir, partialMatch); foreach (Match match in matches) { match.AddNode(node); } break; case PhoneticShapeNode.NodeType.SEGMENT: Segment seg = (Segment)node; PhoneticShapeNode nextNode = node.GetNext(dir); List <Match> segMatches = new List <Match>(); foreach (TrieNode child in m_children) { // check for unifiability when searching if (seg.FeatureValues.FeatureSystem.HasFeatures) { if (seg.FeatureValues.IsUnifiable(child.m_segDef.SynthFeatures)) { segMatches.AddRange(child.Search(nextNode, dir, partialMatch)); } } else if (seg.IsSegmentInstantiated(child.m_segDef)) { segMatches.AddRange(child.Search(nextNode, dir, partialMatch)); } } // if this is an optional node, we can try skipping it if (node.IsOptional) { segMatches.AddRange(Search(nextNode, dir, partialMatch)); } matches = segMatches; foreach (Match match in matches) { match.AddNode(node); } break; } if (partialMatch) { foreach (T value in m_values) { matches.Add(new Match(value)); } } return(matches); }
/// <summary> /// Adds the specified phonetic shape node. /// </summary> /// <param name="seg">The phonetic shape node.</param> internal void Add(PhoneticShapeNode node) { Add(node, -1); }