Exemple #1
0
        public void MergeNext()
        {
            BidiLink firstNext  = _next;
            BidiLink secondNext = firstNext._next;

            _next   = secondNext;
            length += firstNext.length;
        }
Exemple #2
0
        public LevelRun(BidiLink firstLink, BidiLink lastLink, CharType sor, CharType eor)
        {
            this.FirstLink = firstLink;
            this.LastLink  = lastLink;

            switch (sor)
            {
            case CharType.L:
                _extrema |= Extrema.SOR_L;
                break;

            case CharType.R:
                _extrema |= Extrema.SOR_R;
                break;

#if DEBUG
            default:
                throw (new ArgumentException("The type of SOR should be either L or R."));
#endif
            }

            switch (eor)
            {
            case CharType.L:
                _extrema |= Extrema.EOR_L;
                break;

            case CharType.R:
                _extrema |= Extrema.EOR_R;
                break;

#if DEBUG
            default:
                throw (new ArgumentException("The type of EOR should be either L or R."));
#endif
            }

            // An isolating run ends at an isolating initiator.
            switch (lastLink.type)
            {
            case CharType.LRI:
            case CharType.RLI:
            case CharType.FSI:
                _kind |= Kind.Isolate | Kind.Partial;
                break;
            }

            // A terminating run starts with a PDI.
            if (firstLink.type == CharType.PDI)
            {
                _kind |= Kind.Terminating;
            }

            this.SubsequentLink = lastLink.Next;
        }
        private void ResolveImplicitLevels()
        {
            if ((_level & 1) == 0)
            {
                for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
                {
                    CharType type = link.type;

#if DEBUG
                    ValidateTypeForImplicitRules(type);
#endif

                    // Rule I1
                    if (type == CharType.R)
                    {
                        link.level += 1;
                    }
                    else if (type != CharType.L)
                    {
                        link.level += 2;
                    }
                }
            }
            else
            {
                for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
                {
                    CharType type = link.type;

#if DEBUG
                    ValidateTypeForImplicitRules(type);
#endif

                    // Rule I2
                    if (type != CharType.R)
                    {
                        link.level += 1;
                    }
                }
            }
        }
        public void ClosePair(BidiLink closingLink, int bracket)
        {
            List list = _rearList;
            int  top  = _rearTop;

            for (; ;)
            {
                bool isFrontList = (list == _frontList);
                int  limit       = (isFrontList ? _frontTop : 0);

                do
                {
                    BracketPair pair = list.Pairs[top];
                    if (pair.openingLink != null &&
                        pair.closingLink == null &&
                        pair.bracketUnicode == bracket)
                    {
                        pair.closingLink = closingLink;
                        InvalidatePairs(list, top);

                        if (isFrontList && top == _frontTop)
                        {
                            _shouldDequeue = true;
                        }

                        return;
                    }
                } while (top-- > limit);

                if (isFrontList)
                {
                    break;
                }

                list = list.previous;
                top  = List.MaxIndex;
            }
            ;
        }
        public void Resolve()
        {
            // Attach level run links to form isolating run.
            AttachLevelRunLinks();
            // Save last subsequent link.
            BidiLink subsequentLink = _lastRun.SubsequentLink;

            // Rules W1-W7
            BidiLink finalLink = ResolveWeakTypes();

            // Rule N0
            ResolveBrackets();
            // Rules N1, N2
            ResolveNeutrals();
            // Rules I1, I2
            ResolveImplicitLevels();

            // Re-attach original links.
            AttachOriginalLinks();
            // Attach last subsequent link with new final link.
            finalLink.ReplaceNext(subsequentLink);
        }
Exemple #6
0
 public void ReplaceNext(BidiLink next)
 {
     _next = next;
 }
Exemple #7
0
 public void AbandonNext()
 {
     _next = _next._next;
 }
 public IsolatingRun()
 {
     _bracketQueue = new BracketQueue(CharType.L);
     _roller       = new BidiLink();
 }
        private void ResolveNeutrals()
        {
            CharType strongType  = _sos;
            BidiLink neutralLink = null;

            for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
            {
                CharType type = link.type;

#if DEBUG
                ValidateTypeForNeutralRules(type);
#endif

                switch (type)
                {
                case CharType.L:
                    strongType = CharType.L;
                    break;

                case CharType.R:
                case CharType.EN:
                case CharType.AN:
                    strongType = CharType.R;
                    break;

                case CharType.B:
                case CharType.S:
                case CharType.WS:
                case CharType.ON:
                case CharType.LRI:
                case CharType.RLI:
                case CharType.FSI:
                case CharType.PDI:
                    if (neutralLink == null)
                    {
                        neutralLink = link;
                    }

                    CharType nextType = link.Next.type;
                    switch (nextType)
                    {
                    case CharType.Nil:
                        nextType = _eos;
                        break;

                    case CharType.EN:
                    case CharType.AN:
                        nextType = CharType.R;
                        break;
                    }

                    if (nextType == CharType.R || nextType == CharType.L)
                    {
                        // Rules N1, N2
                        CharType resolvedType = (strongType == nextType
                                                     ? strongType
                                                     : Level.MakeEmbeddingType(_level)
                                                 );

                        do
                        {
                            neutralLink.type = resolvedType;
                            neutralLink      = neutralLink.Next;
                        } while (neutralLink != link.Next);

                        neutralLink = null;
                    }
                    break;
                }
            }
        }
        private void ResolveAvailableBracketPairs()
        {
            CharType embeddingDirection = Level.MakeEmbeddingType(_level);
            CharType oppositeDirection  = Level.MakeOppositeType(_level);

            while (!_bracketQueue.IsEmpty)
            {
                BracketPair pair = _bracketQueue.Peek();

                if (pair.IsComplete)
                {
                    CharType innerStrongType = pair.innerStrongType;
                    CharType pairType;

                    // Rule: N0.b
                    if (innerStrongType == embeddingDirection)
                    {
                        pairType = innerStrongType;
                    }
                    // Rule: N0.c
                    else if (innerStrongType == oppositeDirection)
                    {
                        BidiLink priorStrongLink;
                        CharType priorStrongType;

                        priorStrongLink = pair.priorStrongLink;

                        if (priorStrongLink != null)
                        {
                            priorStrongType = priorStrongLink.type;
                            if (priorStrongType == CharType.EN || priorStrongType == CharType.AN)
                            {
                                priorStrongType = CharType.R;
                            }

                            BidiLink link  = priorStrongLink.Next;
                            BidiLink start = pair.openingLink;

                            while (link != start)
                            {
                                CharType type = link.type;
                                if (type == CharType.L || type == CharType.R)
                                {
                                    priorStrongType = type;
                                }

                                link = link.Next;
                            }
                        }
                        else
                        {
                            priorStrongType = _sos;
                        }

                        // Rule: N0.c.1
                        if (priorStrongType == oppositeDirection)
                        {
                            pairType = oppositeDirection;
                        }
                        // Rule: N0.c.2
                        else
                        {
                            pairType = embeddingDirection;
                        }
                    }
                    // Rule: N0.d
                    else
                    {
                        pairType = CharType.Nil;
                    }

                    if (pairType != CharType.Nil)
                    {
                        // Do the substitution
                        pair.openingLink.type = pairType;
                        pair.closingLink.type = pairType;
                    }
                }

                _bracketQueue.Dequeue();
            }
        }
        private void ResolveBrackets()
        {
            BidiLink strongLink = null;

            _bracketQueue.Clear(Level.MakeEmbeddingType(_level));

            for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
            {
                CharType type = link.type;

                switch (type)
                {
                case CharType.ON:
                    BracketType bracketType;

                    char ch           = _text[link.offset];
                    int  bracketValue = PairingLookup.DetermineBracketPair((int)ch, out bracketType);

                    switch (bracketType)
                    {
                    case BracketType.Open:
                        BracketPair bracketPair = new BracketPair()
                        {
                            bracketUnicode  = ch,
                            openingLink     = link,
                            priorStrongLink = strongLink
                        };
                        _bracketQueue.Enqueue(bracketPair);
                        break;

                    case BracketType.Close:
                        if (!_bracketQueue.IsEmpty)
                        {
                            _bracketQueue.ClosePair(link, bracketValue);

                            if (_bracketQueue.ShouldDequeue)
                            {
                                ResolveAvailableBracketPairs();
                            }
                        }
                        break;
                    }
                    break;

                case CharType.L:
                case CharType.R:
                case CharType.AL:
                case CharType.EN:
                case CharType.AN:
                    if (!_bracketQueue.IsEmpty)
                    {
                        if (type == CharType.EN || type == CharType.AN)
                        {
                            type = CharType.R;
                        }

                        _bracketQueue.SetStrongType(type);
                    }
                    strongLink = link;
                    break;
                }
            }

            ResolveAvailableBracketPairs();
        }
        private BidiLink ResolveWeakTypes()
        {
            BidiLink priorLink = _roller;

            CharType w1PriorType  = _sos;
            CharType w2StrongType = _sos;

            for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
            {
                CharType type = link.type;

                // Rule W1
                if (type == CharType.NSM)
                {
                    // Change the 'type' variable as well because it can be EN on which
                    // W2 depends.
                    switch (w1PriorType)
                    {
                    case CharType.LRI:
                    case CharType.RLI:
                    case CharType.FSI:
                    case CharType.PDI:
                        link.type = type = CharType.ON;
                        break;

                    default:
                        link.type = type = w1PriorType;
                        break;
                    }
                }
                w1PriorType = type;

                // Rule W2
                if (type == CharType.EN)
                {
                    if (w2StrongType == CharType.AL)
                    {
                        link.type = CharType.AN;
                    }
                }
                // Rule W3
                // Note: It is safe to apply W3 in 'else-if' statement because it only
                //       depends on type AL. Even if W2 changes EN to AN, there won't
                //       be any harm.
                else if (type == CharType.AL)
                {
                    link.type = CharType.R;
                }

                // Save the strong type for W2.
                switch (type)
                {
                case CharType.L:
                case CharType.AL:
                case CharType.R:
                    w2StrongType = type;
                    break;
                }

                if (type != CharType.ON && priorLink.type == type)
                {
                    priorLink.MergeNext();
                }
                else
                {
                    priorLink = link;
                }
            }

            priorLink = _roller;
            CharType w4PriorType  = _sos;
            CharType w5PriorType  = _sos;
            CharType w7StrongType = _sos;

            for (BidiLink link = _roller.Next; link != _roller; link = link.Next)
            {
                CharType type     = link.type;
                CharType nextType = link.Next.type;

                // Rule W4
                if (link.length == 1 &&
                    (type == CharType.ES || type == CharType.CS) &&
                    (w4PriorType == CharType.EN || w4PriorType == CharType.AN) &&
                    (w4PriorType == nextType) &&
                    (w4PriorType == CharType.EN || type == CharType.CS))
                {
                    // Change the current type as well because it can be EN on which W7
                    // depends.
                    link.type = type = w4PriorType;
                }
                w4PriorType = type;

                // Rule W5
                if (type == CharType.ET &&
                    (w5PriorType == CharType.EN || nextType == CharType.EN))
                {
                    // Change the current type as well because it is EN on which W7
                    // depends.
                    link.type = type = CharType.EN;
                }
                w5PriorType = type;

                switch (type)
                {
                // Rule W6
                case CharType.ET:
                case CharType.CS:
                case CharType.ES:
                    link.type = CharType.ON;
                    break;

                // Rule W7
                // Note: W7 is expected to be applied after W6. However this is not the
                //       case here. The reason is that W6 can only create the type ON
                //       which is not tested in W7 by any means. So it won't affect the
                //       algorithm.
                case CharType.EN:
                    if (w7StrongType == CharType.L)
                    {
                        link.type = CharType.L;
                    }
                    break;

                // Save the strong type for W7.
                // Note: The strong type is expected to be saved after applying W7
                //       because W7 itself creates a strong type. However the strong type
                //       being saved here is based on the type after W5.
                //       This won't effect the algorithm because a single link contains
                //       all consecutive EN types. This means that even if W7 creates a
                //       strong type, it will be saved in next iteration.
                case CharType.L:
                case CharType.R:
                    w7StrongType = type;
                    break;
                }

                if (type != CharType.ON && priorLink.type == type)
                {
                    priorLink.MergeNext();
                }
                else
                {
                    priorLink = link;
                }
            }

            return(priorLink);
        }