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 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 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;
			}
			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;
			}
Esempio n. 5
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;
		}
Esempio n. 6
0
		/// <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(GetNextShapeNode(node, 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(Owner, instantiatedVars));
					return matches;
				}
				else
				{
					return n.Match(node, dir, mode, instantiatedVars);
				}
			}
		}
Esempio n. 7
0
		/// <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)
		{
			switch (node.Type)
			{
				case 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);

				case PhoneticShapeNode.NodeType.BOUNDARY:
					return Match(GetNextShapeNode(node, dir), dir, mode, instantiatedVars);
			}

			return new List<Match>();
		}
Esempio n. 8
0
		/// <summary>
		/// Checks if the specified phonetic shape node matches this simple 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)
		{
			switch (node.Type)
			{
				case PhoneticShapeNode.NodeType.BOUNDARY:
					// only check boundaries in synthesis mode when the pattern is a target,
					// otherwise skip
					if (mode == ModeType.SYNTHESIS)
					{
						if (Owner.IsTarget)
						{
							return new List<Match>();
						}
						else
						{
							IList<Match> bdryMatches = Match(GetNextShapeNode(node, dir), dir, mode, instantiatedVars);
							foreach (Match match in bdryMatches)
								match.Add(node, m_partition);
							return bdryMatches;
						}
					}
					else
					{
						return Match(GetNextShapeNode(node, dir), dir, mode, instantiatedVars);
					}

				case PhoneticShapeNode.NodeType.MARGIN:
					Margin margin = node as Margin;
					if (dir == margin.MarginType)
						// we are at the end of the shape, so no match
						return new List<Match>();
					else
						return Match(GetNextShapeNode(node, dir), dir, mode, instantiatedVars);

				case PhoneticShapeNode.NodeType.SEGMENT:
					Segment seg = node as Segment;
					if (mode == ModeType.SYNTHESIS && Owner.IsTarget)
					{
						// check segment to see if it has already been altered by another
						// subrule, only matters for simultaneously applying rules
						if (!seg.IsClean)
							return new List<Match>();
					}

					VariableValues tempVars = instantiatedVars.Clone();
					if (m_featSys.HasFeatures)
					{
						if (!IsFeatureMatch(seg, tempVars, mode))
							return new List<Match>();
					}
					else
					{
						if (!IsSegmentMatch(seg))
							return new List<Match>();
					}

					// move to the next node
					IList<Match> segMatches = MatchNext(node, dir, mode, tempVars);
					foreach (Match match in segMatches)
						match.Add(node, m_partition);

					return segMatches;
			}

			return new List<Match>();
		}
Esempio n. 9
0
		/// <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>();
		}