コード例 #1
0
ファイル: PhoneticPattern.cs プロジェクト: sillsdev/WorldPad
        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);
        }
コード例 #2
0
        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);
                }
            }
        }
コード例 #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 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);
            }
コード例 #5
0
        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);
                }
            }
        }
コード例 #6
0
            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);
            }
コード例 #7
0
        /// <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);
                }
            }
        }
コード例 #8
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);
            }
コード例 #9
0
ファイル: PhoneticPattern.cs プロジェクト: sillsdev/WorldPad
        /// <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);
        }
コード例 #10
0
ファイル: Stratum.cs プロジェクト: cambell-prince/FieldWorks
            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;
                }
            }
コード例 #11
0
ファイル: PhoneticPattern.cs プロジェクト: sillsdev/WorldPad
        /// <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);
        }
コード例 #12
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));
                }
            }
        }
コード例 #13
0
        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;
                }
            }
        }
コード例 #14
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>());
        }
コード例 #15
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);
            }
コード例 #16
0
            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);
            }
コード例 #17
0
        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);
        }
コード例 #18
0
        /// <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;
                }
            }
        }
コード例 #19
0
        /// <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);
                }
            }
        }
コード例 #20
0
            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);
            }
コード例 #21
0
ファイル: PhoneticPattern.cs プロジェクト: sillsdev/WorldPad
        /// <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);
        }
コード例 #22
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);
        }
コード例 #23
0
        /// <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);
        }
コード例 #24
0
            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;
                    }
                }
            }
コード例 #25
0
        /// <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);
            }
        }
コード例 #26
0
        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);
        }
コード例 #27
0
        /// <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);
        }
コード例 #28
0
ファイル: Stratum.cs プロジェクト: cambell-prince/FieldWorks
 public void AddNode(PhoneticShapeNode node)
 {
     m_nodes.Insert(0, node);
 }
コード例 #29
0
ファイル: Stratum.cs プロジェクト: cambell-prince/FieldWorks
            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);
            }
コード例 #30
0
ファイル: PhoneticPattern.cs プロジェクト: sillsdev/WorldPad
 /// <summary>
 /// Adds the specified phonetic shape node.
 /// </summary>
 /// <param name="seg">The phonetic shape node.</param>
 internal void Add(PhoneticShapeNode node)
 {
     Add(node, -1);
 }