示例#1
0
            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;
                }
            }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
            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);
            }
示例#5
0
            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);
            }
示例#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(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));
                }
            }
        }
示例#7
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);
        }
示例#8
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(node.GetNext(dir), dir, mode, instantiatedVars));
            }

            return(new List <Match>());
        }
示例#9
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);
        }
示例#10
0
            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);
            }
示例#11
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(node.GetNext(dir), dir, mode, instantiatedVars);
                        foreach (Match match in bdryMatches)
                        {
                            match.Add(node, m_partition);
                        }
                        return(bdryMatches);
                    }
                }
                else
                {
                    return(Match(node.GetNext(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(node.GetNext(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>());
        }