示例#1
0
 private void UpdateCacheOnTheFly(UnparsableAst self, State state)
 {
     if (state == State.Before)
     {
         if (self.SyntaxParent == null)
         {
             topAncestorCacheForLeft = null;     // self is root node
         }
         else if (self.IsLeftSiblingCalculated && self.LeftSibling != null)
         {
             topAncestorCacheForLeft = self;
         }
         else
         {
             topAncestorCacheForLeft = UnparsableAst.NonCalculated;
         }
     }
     else if (state == State.After)
     {
         if (direction == Unparser.Direction.LeftToRight && self.BnfTerm is Terminal)
         {
             leftTerminalLeaveCache = self;
         }
         else if (direction == Unparser.Direction.RightToLeft && self == topAncestorCacheForLeft)
         {
             leftTerminalLeaveCache = UnparsableAst.NonCalculated;
         }
     }
 }
示例#2
0
        internal FormatYielder Spawn(UnparsableAst child, ChildLocation childLocation = ChildLocation.Unknown)
        {
            if (childLocation == ChildLocation.Unknown)
            {
                return(new FormatYielder(this)
                {
                    topAncestorCacheForLeft = UnparsableAst.NonCalculated
                });
            }
            else
            {
                bool isLeftMostChild =
                    childLocation == ChildLocation.Only
                    ||
                    direction == Unparser.Direction.LeftToRight && childLocation == ChildLocation.First
                    ||
                    direction == Unparser.Direction.RightToLeft && childLocation == ChildLocation.Last;

                return(new FormatYielder(this)
                {
                    topAncestorCacheForLeft = isLeftMostChild
                        ? this.topAncestorCacheForLeft
                        : (child ?? UnparsableAst.NonCalculated)
                });
            }
        }
示例#3
0
        private IEnumerable <UtokenBase> YieldIndentationRight(UnparsableAst self, ref BlockIndentation blockIndentation)
        {
            Unparser.tsUnparse.Debug("YieldIndentationRight");

            try
            {
                // NOTE: topAncestorCacheForLeft may get updated by YieldIndentation
                // NOTE: ToList is needed to fully evaluate the called function, so we can catch the exception
                return(_YieldIndentation(self, ref blockIndentation, direction, formatYielder: this, left: false).ToList());
            }
            catch (NonCalculatedException)
            {
                // top left node or someone in the chain is non-calculated -> defer execution
                Debug.Assert(blockIndentation == BlockIndentation.ToBeSet || blockIndentation.IsDeferred());

                if (blockIndentation == BlockIndentation.ToBeSet)
                {
                    blockIndentation = BlockIndentation.Defer();
                }

                Debug.Assert(blockIndentation.IsDeferred());

                BlockIndentation _blockIndentation = blockIndentation;

                return(new[]
                {
                    blockIndentation.RightDeferred = new DeferredUtokens(
                        () => _YieldIndentation(self, _blockIndentation, direction, formatYielder: this, left: false),
                        self: self,
                        helpMessage: "YieldIndentationRight",
                        helpCalculatedObject: _blockIndentation
                        )
                });
            }
        }
示例#4
0
 private void CheckIfNotThrownOut(UnparsableAst relative, [CallerMemberName] string nameOfRelative = "")
 {
     if (IsThrownOut(relative))
     {
         throw new ThrownOutException(string.Format("Tried to set a thrown out relative '{0}' for {1}", nameOfRelative, this));
     }
 }
示例#5
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated.
        /// </exception>
        private static IEnumerable <UnparsableAst> GetLeftsFromTopToBottom(UnparsableAst self, FormatYielder formatYielder = null)
        {
            UnparsableAst topAncestorForLeft = GetTopAncestorForLeft(self, formatYielder);

            return(topAncestorForLeft != null
                ? Util.RecurseStopBeforeNull(topAncestorForLeft.LeftSibling, current => current.RightMostChild)
                : Enumerable.Empty <UnparsableAst>());
        }
示例#6
0
 public bool Equals(UnparsableAst that)
 {
     return(object.ReferenceEquals(this, that)
            ||
            !object.ReferenceEquals(that, null) &&
            this.BnfTerm == that.BnfTerm &&
            this.AstValue == that.AstValue);
 }
示例#7
0
        internal IDecoration GetDecoration(Utoken utoken)
        {
            UnparsableAst target = utoken is UtokenText
                ? ((UtokenText)utoken).Reference
                : null;

            return(GetDecoration(utoken, target));
        }
示例#8
0
        private UnparsableAst GetParenthesis(ParenthesisKind parenthesisKind, UnparsableAst unparsableExpression)
        {
            BnfTerm parenthesis = parenthesisKind == ParenthesisKind.Left
                ? GetSurroundingParentheses().LeftParenthesis
                : GetSurroundingParentheses().RightParenthesis;

            return(new UnparsableAst(parenthesis, unparsableExpression.AstValue));
        }
示例#9
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable <UtokenBase> _YieldIndentation(UnparsableAst self, ref BlockIndentation blockIndentationParameter, Unparser.Direction direction,
                                                                  FormatYielder formatYielder, bool left)
        {
            if (!left && direction == Unparser.Direction.RightToLeft && blockIndentationParameter.IsDeferred() && blockIndentationParameter.LeftDeferred != null)
            {
                /*
                 * We are in a right-to-left unparse and this deferred right indentation depends on a deferred left indentation,
                 * so let's try to calculate the deferred left indentation, which - if succeed - will change the shared blockIndentation
                 * object state from deferred to a valid indentation.
                 *
                 * (If the left indentation wasn't deferred then it would be calculated which means that the shared blockIndentation
                 * object won't be deferred.)
                 * */
                blockIndentationParameter.LeftDeferred.CalculateUtokens();

                // either CalculateUtokens succeeded, and blockIndentation is not deferred, or CalculateUtokens threw a NonCalculatedException exception

                Debug.Assert(!blockIndentationParameter.IsDeferred(), "CalculateUtokens succeeded, but blockIndentation remained deferred");
            }

            if (blockIndentationParameter == BlockIndentation.ToBeSet || blockIndentationParameter.IsDeferred())
            {
                UnparsableAst    leftObject       = GetLeftTerminalLeave(self);
                BlockIndentation blockIndentation = formatYielder._GetBlockIndentation(leftObject, self);

                // NOTE: topAncestorCacheForLeft gets updated by GetUsedLeftsFromTopToBottomB

                if (blockIndentation != BlockIndentation.IndentNotNeeded)
                {
                    Unparser.tsUnparse.Debug("blockindentation {0} for leftTarget '{1}' and for target '{2}'", blockIndentation, leftObject, self);
                }

                Debug.Assert(!blockIndentation.IsDeferred());

                if (blockIndentationParameter == BlockIndentation.ToBeSet)
                {
                    blockIndentationParameter = blockIndentation;
                }
                else
                {
                    blockIndentationParameter.CopyKindFrom(blockIndentation);
                }
            }

            if (direction == Unparser.Direction.LeftToRight)
            {
                return(left
                    ? BlockIndentationToUtokenControlBefore(blockIndentationParameter)
                    : BlockIndentationToUtokenControlAfter(blockIndentationParameter));
            }
            else
            {
                return(left
                    ? BlockIndentationToUtokenControlAfter(blockIndentationParameter)
                    : BlockIndentationToUtokenControlBefore(blockIndentationParameter));
            }
        }
示例#10
0
        public DeferredUtokens(Func <IEnumerable <UtokenBase> > utokenYielder, UnparsableAst self, string helpMessage = null, object helpCalculatedObject = null)
        {
            this.utokenYielder        = utokenYielder;
            this.Self                 = self;
            this.helpMessage          = helpMessage;
            this.helpCalculatedObject = helpCalculatedObject;
            this.calculatedUtokens    = null;

            self.IsLeftSiblingNeededForDeferredCalculation = true;
        }
示例#11
0
        public IEnumerable <UtokenBase> Unparse(UnparsableAst self, IEnumerable <UnparsableAst> children, Unparser.Direction direction)
        {
            if (ongoingExpressionUnparseLevel == 0)
            {
                ResetMutableState();
                this.direction = direction;
            }

            using (ongoingExpressionUnparseLevel.IncrAutoDecr())
                return(Unparse(self, children, initialization: false));
        }
示例#12
0
        private IEnumerable <UtokenBase> YieldIndentationRight(UnparsableAst self, BlockIndentation blockIndentation)
        {
#if DEBUG
            BlockIndentation originalBlockIndentation = blockIndentation;
#endif
            var utokens = YieldIndentationRight(self, ref blockIndentation);
#if DEBUG
            Debug.Assert(object.ReferenceEquals(blockIndentation, originalBlockIndentation), "unwanted change of blockIndentationParameter reference in YieldIndentationRight");
#endif
            return(utokens);
        }
示例#13
0
        /// <summary>
        /// This method needs to be fully executed before UnparseRawMiddle because this method modifies the state of Unparser and,
        /// which state is used by UnparseRawMiddle. Thus, always call this method prior to UnparseRawMiddle.
        /// </summary>
        internal IEnumerable <UtokenBase> YieldBefore(UnparsableAst self, out Params @params)
        {
            /*
             * To achieve fully execution before UnparseRawMiddle, this method is not an iterator block rather populates a list.
             * Returning IReadOnlyList instead of IEnumerable is just an explicit guarantee to the caller to ensure that
             * the returned utokens does not need to be iterated through e.g. by converting it to a list in order to achieve full execution.
             * */

            Unparser.tsUnparse.Debug("YieldBefore");

            UpdateCacheOnTheFly(self, State.Before);

            var utokens = new List <UtokenBase>();
            BlockIndentation blockIndentation = BlockIndentation.ToBeSet;

            if (direction == Unparser.Direction.LeftToRight)
            {
                utokens.AddRange(YieldBetween(self));
                utokens.AddRange(YieldIndentationLeft(self, ref blockIndentation));
            }
            else
            {
                utokens.AddRange(YieldIndentationRight(self, ref blockIndentation));
            }

            InsertedUtokens leftInsertedUtokens;
            InsertedUtokens rightInsertedUtokens;

            _GetUtokensAround(self, out leftInsertedUtokens, out rightInsertedUtokens);

            InsertedUtokens insertedUtokensBefore;
            InsertedUtokens insertedUtokensAfter;

            if (direction == Unparser.Direction.LeftToRight)
            {
                insertedUtokensBefore = leftInsertedUtokens;
                insertedUtokensAfter  = rightInsertedUtokens;
            }
            else
            {
                insertedUtokensBefore = rightInsertedUtokens;
                insertedUtokensAfter  = leftInsertedUtokens;
            }

            if (insertedUtokensBefore != InsertedUtokens.None)
            {
                Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensBefore);
                utokens.Add(insertedUtokensBefore);
            }

            @params = new Params(blockIndentation, insertedUtokensAfter);

            return(utokens);
        }
示例#14
0
 private void CheckIfValid(UnparsableAst relative, [CallerMemberName] string nameOfRelative = "")
 {
     if (!IsCalculated(relative))
     {
         throw new NonCalculatedException(string.Format("Tried to use a non-calculated relative '{0}' for {1}", nameOfRelative, this));
     }
     else if (IsThrownOut(relative))
     {
         throw new ThrownOutException(string.Format("Tried to use a thrown out relative '{0}' for {1}", nameOfRelative, this));
     }
 }
示例#15
0
        private void _GetUtokensAround(UnparsableAst target, out InsertedUtokens leftInsertedUtokens, out InsertedUtokens rightInsertedUtokens)
        {
            formatter.GetUtokensAround(target, out leftInsertedUtokens, out rightInsertedUtokens);

            leftInsertedUtokens
            .SetKind(InsertedUtokens.Kind.Left)
            .SetAffected(target);

            rightInsertedUtokens
            .SetKind(InsertedUtokens.Kind.Right)
            .SetAffected(target);
        }
示例#16
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable <UtokenBase> _YieldIndentation(UnparsableAst self, BlockIndentation blockIndentationParameter, Unparser.Direction direction,
                                                                  FormatYielder formatYielder, bool left)
        {
#if DEBUG
            BlockIndentation originalBlockIndentationParameter = blockIndentationParameter;
#endif
            var utokens = _YieldIndentation(self, ref blockIndentationParameter, direction, formatYielder, left);
#if DEBUG
            Debug.Assert(object.ReferenceEquals(blockIndentationParameter, originalBlockIndentationParameter),
                         string.Format("unwanted change of blockIndentationParameter reference in _YieldIndentation ({0})", left ? "left" : "right"));
#endif
            return(utokens);
        }
示例#17
0
 public virtual string[] GetDecoratedCommentTextLines(UnparsableAst owner, Comment comment)
 {
     if (comment.TextLines.Length > 1)
     {
         return(comment.TextLines
                .Select((textLine, lineIndex) => lineIndex > 0 && comment.IsDecorated ? MultiLineCommentDecorator + textLine : textLine)
                .ToArray());
     }
     else
     {
         return(comment.TextLines);
     }
 }
示例#18
0
        internal static int? DebugWriteLinePriority(this int? priority, TraceSource ts, UnparsableAst unparsableAst, string messageBefore = "", string messageAfter = "", string messageInside = "")
        {
            ts.Debug(
                "{0}{1}{2} obj: {3}; priority = {4}{5}",
                messageBefore,
                unparsableAst.BnfTerm,
                messageInside != "" ? " " + messageInside : messageInside,
                unparsableAst.AstValue != null ? unparsableAst.AstValue.ToString() : "<<NULL>>",
                priority.HasValue ? priority.ToString() : "NULL",
                messageAfter
                );

            return priority;
        }
示例#19
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable <UtokenBase> _YieldBetween(UnparsableAst self, FormatYielder formatYielder)
        {
            // NOTE: topAncestorCacheForLeft may get updated by GetUsedLeftsFromTopToBottomB

            UnparsableAst leftObject = GetLeftTerminalLeave(self);

            if (leftObject != null)
            {
                InsertedUtokens insertedUtokensBetween = formatYielder._GetUtokensBetween(leftObject, self);

                if (insertedUtokensBetween != InsertedUtokens.None)
                {
                    Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensBetween);
                    yield return(insertedUtokensBetween);
                }
            }
        }
示例#20
0
        internal IEnumerable <UtokenBase> YieldAfterComments(UnparsableAst owner, Comments comments, UnparseCommentDelegate unparseComment)
        {
            IList <Comment> afterComments;
            IList <Comment> afterCommentsForFormatter;
            Func <IEnumerable <Comment>, int, IEnumerable <Comment> > skipOrTake;

            if (direction == Unparser.Direction.LeftToRight)
            {
                afterComments             = comments.Right;
                afterCommentsForFormatter = comments.Right;
                skipOrTake = Enumerable.Take;
            }
            else
            {
                afterComments             = comments.Left.ReverseOptimized();
                afterCommentsForFormatter = comments.Left;
                skipOrTake = Enumerable.Skip;
            }

            foreach (var afterComment in afterComments.Select((beforeComment, commentIndex) => new { Value = beforeComment, Index = commentIndex }))
            {
                int index;
                int commentCountToSkipOrTake;

                if (direction == Unparser.Direction.LeftToRight)
                {
                    index = afterComment.Index;
                    commentCountToSkipOrTake = index;
                }
                else
                {
                    index = afterComments.Count - 1 - afterComment.Index;
                    commentCountToSkipOrTake = index + 1;
                }

                yield return(formatter.GetUtokensBetweenCommentAndOwner(owner, afterComment.Value, index, afterComments.Count, skipOrTake(afterCommentsForFormatter, commentCountToSkipOrTake))
                             .SetKind(InsertedUtokens.Kind.Between)
                             .SetAffected(owner));

                foreach (UtokenBase utoken in unparseComment(owner, afterComment.Value))
                {
                    yield return(utoken);
                }
            }
        }
示例#21
0
        public virtual InsertedUtokens GetUtokensBetweenCommentAndOwner(UnparsableAst owner, Comment comment, int commentIndex, int commentCount,
                                                                        IEnumerable <Comment> commentsBetweenThisAndOwner)
        {
            if (comment.LineIndexDistanceFromOwner > 0)
            {
                int newLinesCount;

                if (comment.Placement == CommentPlacement.OwnerLeft)
                {
                    newLinesCount = comment.LineIndexDistanceFromOwner - (comment.TextLines.Length - 1);

                    Comment nextComment = commentsBetweenThisAndOwner.FirstOrDefault();
                    if (nextComment != null)
                    {
                        newLinesCount -= nextComment.LineIndexDistanceFromOwner;
                    }
                }
                else
                {
                    newLinesCount = comment.LineIndexDistanceFromOwner;

                    Comment prevComment = commentsBetweenThisAndOwner.FirstOrDefault();
                    if (prevComment != null)
                    {
                        newLinesCount -= prevComment.LineIndexDistanceFromOwner + (prevComment.TextLines.Length - 1);
                    }
                }

                if (comment.Placement == CommentPlacement.OwnerLeft && comment.Kind == CommentKind.SingleLine)
                {
                    /*
                     * We have already yielded a NewLine in Unparser.UnparseComment (see comment there),
                     * thus we have to yield one less "formatting" NewLine here.
                     * */
                    newLinesCount--;
                }

                return(new UtokenRepeat(UtokenWhitespace.NewLine(), newLinesCount));
            }
            else
            {
                return(UtokenWhitespace.Space());
            }
        }
示例#22
0
        private IEnumerable <UtokenBase> UnparseRawEager(UnparsableAst unparsableAst, bool initialization, out OperatorInfo operatorInfo)
        {
            if (initialization)
            {
                NonTerminal nonTerminal = unparsableAst.BnfTerm as NonTerminal;

                if (nonTerminal != null)
                {
                    RegisteringExpressionsThatNeedParentheses(nonTerminal);
                }

                operatorInfo = null;
                return(new UtokenBase[0]);
            }
            else
            {
                var utokens = unparser.UnparseRaw(unparsableAst).ToList();
                UpdateOperatorInfo(unparsableAst.BnfTerm);
                operatorInfo = GetOperatorInfo();
                return(utokens);
            }
        }
示例#23
0
        private static string ConvertToString(UnparsableAst reference, IFormatProvider formatProvider)
        {
            if (reference.BnfTerm is DataLiteralBase)
            {
                DataLiteralBase dataLiteral = (DataLiteralBase)reference.BnfTerm;

                string text;

                if (reference.AstValue is DateTime)
                {
                    text = ((DateTime)reference.AstValue).ToString(dataLiteral.DateTimeFormat, formatProvider);
                }

                else if (NumberLiteralInfo.IsNumber(reference.AstValue))
                {
                    text = NumberLiteralInfo.NumberToText(reference.AstValue, dataLiteral.IntRadix, formatProvider);
                }

                else
                {
                    text = Convert.ToString(reference.AstValue, formatProvider);
                }

                return(text);
            }

            else if (reference.BnfTerm is NumberLiteral)
            {
                return(NumberLiteralInfo.NumberToText(reference.AstValue, @base: 10, formatProvider: formatProvider));
            }

            else
            {
                return(Convert.ToString(reference.AstValue, formatProvider));
            }
        }
示例#24
0
        private static UnparsableAst GetTopAncestorForLeft(UnparsableAst self, FormatYielder formatYielder = null)
        {
            // NOTE: topAncestorCacheForLeft will not be changed if we have no formatter, that's why we use topAncestorForLeft + the static vs. instance behavior
            UnparsableAst topAncestorForLeft;

            if (formatYielder == null || !UnparsableAst.IsCalculated(formatYielder.topAncestorCacheForLeft))
            {
                topAncestorForLeft = CalculateTopAncestorForLeft(self);

                if (formatYielder != null)
                {
                    formatYielder.topAncestorCacheForLeft = topAncestorForLeft;
                }
            }
            else
            {
                topAncestorForLeft = formatYielder.topAncestorCacheForLeft;
                //Unparser.tsUnparse.Debug(formatter.topAncestorCacheForLeft != CalculateTopAncestorForLeft(self),
                //    "!!!!!!!! should be equal for {0}, but topAncestorCacheForLeft is '{1}' and calculated value is '{2}'", self, formatter.topAncestorCacheForLeft, CalculateTopAncestorForLeft(self));
                Debug.Assert(formatYielder.topAncestorCacheForLeft == CalculateTopAncestorForLeft(self));
            }

            return(topAncestorForLeft);
        }
示例#25
0
        internal IEnumerable <UtokenBase> YieldAfter(UnparsableAst self, Params @params)
        {
            Unparser.tsUnparse.Debug("YieldAfter");

            InsertedUtokens insertedUtokensAfter = @params.insertedUtokensAfter;

            if (insertedUtokensAfter != InsertedUtokens.None)
            {
                Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensAfter);
                yield return(insertedUtokensAfter);
            }

            BlockIndentation blockIndentation = @params.blockIndentation;

            if (direction == Unparser.Direction.LeftToRight)
            {
                foreach (UtokenBase utoken in YieldIndentationRight(self, blockIndentation))
                {
                    yield return(utoken);
                }
            }
            else
            {
                foreach (UtokenBase utoken in YieldIndentationLeft(self, blockIndentation))
                {
                    yield return(utoken);
                }

                foreach (UtokenBase utoken in YieldBetween(self))
                {
                    yield return(utoken);
                }
            }

            UpdateCacheOnTheFly(self, State.After);
        }
示例#26
0
        private IEnumerable <UtokenBase> YieldBetween(UnparsableAst self)
        {
            Unparser.tsUnparse.Debug("YieldBetween");

            try
            {
                // NOTE: topAncestorCacheForLeft may get updated by _YieldBetween
                // NOTE: ToList is needed to fully evaluate the called function, so we can catch the exception
                return(_YieldBetween(self, formatYielder: this).ToList());
            }
            catch (NonCalculatedException)
            {
                // top left node or someone in the chain is non-calculated -> defer execution

                return(new[]
                {
                    new DeferredUtokens(
                        () => _YieldBetween(self, formatYielder: this),
                        self: self,
                        helpMessage: "YieldBetween"
                        )
                });
            }
        }
示例#27
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated.
        /// </exception>
        private static UnparsableAst GetLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder = null)
        {
            // NOTE: topAncestorCacheForLeft will not be changed if we have no formatter, that's why we use topAncestorForLeft + the static vs. instance behavior
            UnparsableAst leftTerminalLeave;

            if (formatYielder == null || !UnparsableAst.IsCalculated(formatYielder.topAncestorCacheForLeft))
            {
                leftTerminalLeave = CalculateLeftTerminalLeave(self, formatYielder);

                if (formatYielder != null)
                {
                    formatYielder.leftTerminalLeaveCache = leftTerminalLeave;
                }
            }
            else
            {
                leftTerminalLeave = formatYielder.leftTerminalLeaveCache;
                //Unparser.tsUnparse.Debug(formatter.leftTerminalLeaveCache != CalculateLeftTerminalLeave(self, formatter),
                //    "!!!!!!!! should be equal for {0}, but leftTerminalLeaveCache is '{1}' and calculated value is '{2}'", self, formatter.leftTerminalLeaveCache, CalculateLeftTerminalLeave(self, formatter));
                Debug.Assert(formatYielder.leftTerminalLeaveCache == CalculateLeftTerminalLeave(self, formatYielder));
            }

            return(leftTerminalLeave);
        }
示例#28
0
 internal void ResetMutableState()
 {
     topAncestorCacheForLeft = UnparsableAst.NonCalculated;
 }
示例#29
0
        public virtual InsertedUtokens GetUtokensBetweenCommentAndOwner(UnparsableAst owner, Comment comment, int commentIndex, int commentCount,
            IEnumerable<Comment> commentsBetweenThisAndOwner)
        {
            if (comment.LineIndexDistanceFromOwner > 0)
            {
                int newLinesCount;

                if (comment.Placement == CommentPlacement.OwnerLeft)
                {
                    newLinesCount = comment.LineIndexDistanceFromOwner - (comment.TextLines.Length - 1);

                    Comment nextComment = commentsBetweenThisAndOwner.FirstOrDefault();
                    if (nextComment != null)
                        newLinesCount -= nextComment.LineIndexDistanceFromOwner;
                }
                else
                {
                    newLinesCount = comment.LineIndexDistanceFromOwner;

                    Comment prevComment = commentsBetweenThisAndOwner.FirstOrDefault();
                    if (prevComment != null)
                        newLinesCount -= prevComment.LineIndexDistanceFromOwner + (prevComment.TextLines.Length - 1);
                }

                if (comment.Placement == CommentPlacement.OwnerLeft && comment.Kind == CommentKind.SingleLine)
                {
                    /*
                     * We have already yielded a NewLine in Unparser.UnparseComment (see comment there),
                     * thus we have to yield one less "formatting" NewLine here.
                     * */
                    newLinesCount--;
                }

                return new UtokenRepeat(UtokenWhitespace.NewLine(), newLinesCount);
            }
            else
                return UtokenWhitespace.Space();
        }
示例#30
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable<UtokenBase> _YieldIndentation(UnparsableAst self, BlockIndentation blockIndentationParameter, Unparser.Direction direction,
            FormatYielder formatYielder, bool left)
        {
#if DEBUG
            BlockIndentation originalBlockIndentationParameter = blockIndentationParameter;
#endif
            var utokens = _YieldIndentation(self, ref blockIndentationParameter, direction, formatYielder, left);
#if DEBUG
            Debug.Assert(object.ReferenceEquals(blockIndentationParameter, originalBlockIndentationParameter),
                string.Format("unwanted change of blockIndentationParameter reference in _YieldIndentation ({0})", left ? "left" : "right"));
#endif
            return utokens;
        }
示例#31
0
 protected override bool TryGetUtokensDirectly(IUnparser unparser, UnparsableAst self, out IEnumerable<UtokenValue> utokens)
 {
     utokens = null;
     return false;
 }
示例#32
0
        /// <summary>
        /// This method needs to be fully executed before UnparseRawMiddle because this method modifies the state of Unparser and,
        /// which state is used by UnparseRawMiddle. Thus, always call this method prior to UnparseRawMiddle.
        /// </summary>
        internal IEnumerable<UtokenBase> YieldBefore(UnparsableAst self, out Params @params)
        {
            /*
             * To achieve fully execution before UnparseRawMiddle, this method is not an iterator block rather populates a list.
             * Returning IReadOnlyList instead of IEnumerable is just an explicit guarantee to the caller to ensure that
             * the returned utokens does not need to be iterated through e.g. by converting it to a list in order to achieve full execution.
             * */

            Unparser.tsUnparse.Debug("YieldBefore");

            UpdateCacheOnTheFly(self, State.Before);

            var utokens = new List<UtokenBase>();
            BlockIndentation blockIndentation = BlockIndentation.ToBeSet;

            if (direction == Unparser.Direction.LeftToRight)
            {
                utokens.AddRange(YieldBetween(self));
                utokens.AddRange(YieldIndentationLeft(self, ref blockIndentation));
            }
            else
            {
                utokens.AddRange(YieldIndentationRight(self, ref blockIndentation));
            }

            InsertedUtokens leftInsertedUtokens;
            InsertedUtokens rightInsertedUtokens;

            _GetUtokensAround(self, out leftInsertedUtokens, out rightInsertedUtokens);

            InsertedUtokens insertedUtokensBefore;
            InsertedUtokens insertedUtokensAfter;

            if (direction == Unparser.Direction.LeftToRight)
            {
                insertedUtokensBefore = leftInsertedUtokens;
                insertedUtokensAfter = rightInsertedUtokens;
            }
            else
            {
                insertedUtokensBefore = rightInsertedUtokens;
                insertedUtokensAfter = leftInsertedUtokens;
            }

            if (insertedUtokensBefore != InsertedUtokens.None)
            {
                Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensBefore);
                utokens.Add(insertedUtokensBefore);
            }

            @params = new Params(blockIndentation, insertedUtokensAfter);

            return utokens;
        }
示例#33
0
        public IEnumerable<UtokenValue> NumberLiteralToText(UnparsableAst reference, IFormatProvider formatProvider)
        {
            INumberLiteral numberLiteral = (INumberLiteral)reference.AstValue;

            string prefix = BaseToPrefix(numberLiteral.Base);
            string body = NumberToText(numberLiteral.Value, (int)numberLiteral.Base, formatProvider, numberLiteral.HasExplicitTypeModifier);
            string suffix = TypeToSuffix(numberLiteral);

            if (!string.IsNullOrEmpty(prefix))
            {
                yield return UtokenValue.CreateText(prefix, reference).SetDiscriminator(Formatter.NumberLiteralBasePrefix);
                yield return UtokenValue.NoWhitespace();
            }

            yield return UtokenValue.CreateText(body, reference).SetDiscriminator(Formatter.NumberLiteralContent);

            if (!string.IsNullOrEmpty(suffix))
            {
                yield return UtokenValue.NoWhitespace();
                yield return UtokenValue.CreateText(suffix, reference).SetDiscriminator(Formatter.NumberLiteralTypeModifierSuffix);
            }
        }
示例#34
0
 internal static bool IsCalculated(UnparsableAst unparsableAst)
 {
     return(!object.ReferenceEquals(unparsableAst, NonCalculated));
 }
示例#35
0
        private IEnumerable<UtokenBase> YieldIndentationRight(UnparsableAst self, BlockIndentation blockIndentation)
        {
#if DEBUG
            BlockIndentation originalBlockIndentation = blockIndentation;
#endif
            var utokens = YieldIndentationRight(self, ref blockIndentation);
#if DEBUG
            Debug.Assert(object.ReferenceEquals(blockIndentation, originalBlockIndentation), "unwanted change of blockIndentationParameter reference in YieldIndentationRight");
#endif
            return utokens;
        }
示例#36
0
 private InsertedUtokens _GetUtokensBetween(UnparsableAst leftTarget, UnparsableAst rightTarget)
 {
     return formatter.GetUtokensBetween(leftTarget, rightTarget)
         .SetKind(InsertedUtokens.Kind.Between)
         .SetAffected(leftTarget, rightTarget);
 }
示例#37
0
        private void _GetUtokensAround(UnparsableAst target, out InsertedUtokens leftInsertedUtokens, out InsertedUtokens rightInsertedUtokens)
        {
            formatter.GetUtokensAround(target, out leftInsertedUtokens, out rightInsertedUtokens);

            leftInsertedUtokens
                .SetKind(InsertedUtokens.Kind.Left)
                .SetAffected(target);

            rightInsertedUtokens
                .SetKind(InsertedUtokens.Kind.Right)
                .SetAffected(target);
        }
示例#38
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable<UtokenBase> _YieldIndentation(UnparsableAst self, ref BlockIndentation blockIndentationParameter, Unparser.Direction direction,
            FormatYielder formatYielder, bool left)
        {
            if (!left && direction == Unparser.Direction.RightToLeft && blockIndentationParameter.IsDeferred() && blockIndentationParameter.LeftDeferred != null)
            {
                /*
                 * We are in a right-to-left unparse and this deferred right indentation depends on a deferred left indentation,
                 * so let's try to calculate the deferred left indentation, which - if succeed - will change the shared blockIndentation
                 * object state from deferred to a valid indentation.
                 * 
                 * (If the left indentation wasn't deferred then it would be calculated which means that the shared blockIndentation
                 * object won't be deferred.)
                 * */
                blockIndentationParameter.LeftDeferred.CalculateUtokens();

                // either CalculateUtokens succeeded, and blockIndentation is not deferred, or CalculateUtokens threw a NonCalculatedException exception

                Debug.Assert(!blockIndentationParameter.IsDeferred(), "CalculateUtokens succeeded, but blockIndentation remained deferred");
            }

            if (blockIndentationParameter == BlockIndentation.ToBeSet || blockIndentationParameter.IsDeferred())
            {
                UnparsableAst leftObject = GetLeftTerminalLeave(self);
                BlockIndentation blockIndentation = formatYielder._GetBlockIndentation(leftObject, self);

                // NOTE: topAncestorCacheForLeft gets updated by GetUsedLeftsFromTopToBottomB

                if (blockIndentation != BlockIndentation.IndentNotNeeded)
                    Unparser.tsUnparse.Debug("blockindentation {0} for leftTarget '{1}' and for target '{2}'", blockIndentation, leftObject, self);

                Debug.Assert(!blockIndentation.IsDeferred());

                if (blockIndentationParameter == BlockIndentation.ToBeSet)
                    blockIndentationParameter = blockIndentation;
                else
                    blockIndentationParameter.CopyKindFrom(blockIndentation);
            }

            if (direction == Unparser.Direction.LeftToRight)
            {
                return left
                    ? BlockIndentationToUtokenControlBefore(blockIndentationParameter)
                    : BlockIndentationToUtokenControlAfter(blockIndentationParameter);
            }
            else
            {
                return left
                    ? BlockIndentationToUtokenControlAfter(blockIndentationParameter)
                    : BlockIndentationToUtokenControlBefore(blockIndentationParameter);
            }
        }
示例#39
0
        internal IEnumerable<UtokenBase> YieldAfterComments(UnparsableAst owner, Comments comments, UnparseCommentDelegate unparseComment)
        {
            IList<Comment> afterComments;
            IList<Comment> afterCommentsForFormatter;
            Func<IEnumerable<Comment>, int, IEnumerable<Comment>> skipOrTake;

            if (direction == Unparser.Direction.LeftToRight)
            {
                afterComments = comments.Right;
                afterCommentsForFormatter = comments.Right;
                skipOrTake = Enumerable.Take;
            }
            else
            {
                afterComments = comments.Left.ReverseOptimized();
                afterCommentsForFormatter = comments.Left;
                skipOrTake = Enumerable.Skip;
            }

            foreach (var afterComment in afterComments.Select((beforeComment, commentIndex) => new { Value = beforeComment, Index = commentIndex }))
            {
                int index;
                int commentCountToSkipOrTake;

                if (direction == Unparser.Direction.LeftToRight)
                {
                    index = afterComment.Index;
                    commentCountToSkipOrTake = index;
                }
                else
                {
                    index = afterComments.Count - 1 - afterComment.Index;
                    commentCountToSkipOrTake = index + 1;
                }

                yield return formatter.GetUtokensBetweenCommentAndOwner(owner, afterComment.Value, index, afterComments.Count, skipOrTake(afterCommentsForFormatter, commentCountToSkipOrTake))
                    .SetKind(InsertedUtokens.Kind.Between)
                    .SetAffected(owner);

                foreach (UtokenBase utoken in unparseComment(owner, afterComment.Value))
                    yield return utoken;
            }
        }
示例#40
0
 private void UpdateCacheOnTheFly(UnparsableAst self, State state)
 {
     if (state == State.Before)
     {
         if (self.SyntaxParent == null)
             topAncestorCacheForLeft = null;     // self is root node
         else if (self.IsLeftSiblingCalculated && self.LeftSibling != null)
             topAncestorCacheForLeft = self;
         else
             topAncestorCacheForLeft = UnparsableAst.NonCalculated;
     }
     else if (state == State.After)
     {
         if (direction == Unparser.Direction.LeftToRight && self.BnfTerm is Terminal)
             leftTerminalLeaveCache = self;
         else if (direction == Unparser.Direction.RightToLeft && self == topAncestorCacheForLeft)
             leftTerminalLeaveCache = UnparsableAst.NonCalculated;
     }
 }
示例#41
0
 public virtual InsertedUtokens GetUtokensBetween(UnparsableAst leftTerminalLeaveTarget, UnparsableAst rightTarget)
 {
     return InsertedUtokens.None;
 }
示例#42
0
 public virtual IDecoration GetDecoration(Utoken utoken, UnparsableAst target)
 {
     return Decoration.None;
 }
示例#43
0
        internal IEnumerable<UtokenBase> YieldAfter(UnparsableAst self, Params @params)
        {
            Unparser.tsUnparse.Debug("YieldAfter");

            InsertedUtokens insertedUtokensAfter = @params.insertedUtokensAfter;

            if (insertedUtokensAfter != InsertedUtokens.None)
            {
                Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensAfter);
                yield return insertedUtokensAfter;
            }

            BlockIndentation blockIndentation = @params.blockIndentation;

            if (direction == Unparser.Direction.LeftToRight)
            {
                foreach (UtokenBase utoken in YieldIndentationRight(self, blockIndentation))
                    yield return utoken;
            }
            else
            {
                foreach (UtokenBase utoken in YieldIndentationLeft(self, blockIndentation))
                    yield return utoken;

                foreach (UtokenBase utoken in YieldBetween(self))
                    yield return utoken;
            }

            UpdateCacheOnTheFly(self, State.After);
        }
示例#44
0
 private static UnparsableAst CalculateTopAncestorForLeft(UnparsableAst self)
 {
     return(GetSelfAndAncestors(self).FirstOrDefault(current => current.LeftSibling != null));
 }
示例#45
0
        internal FormatYielder Spawn(UnparsableAst child, ChildLocation childLocation = ChildLocation.Unknown)
        {
            if (childLocation == ChildLocation.Unknown)
            {
                return new FormatYielder(this)
                {
                    topAncestorCacheForLeft = UnparsableAst.NonCalculated
                };
            }
            else
            {
                bool isLeftMostChild =
                    childLocation == ChildLocation.Only
                    ||
                    direction == Unparser.Direction.LeftToRight && childLocation == ChildLocation.First
                    ||
                    direction == Unparser.Direction.RightToLeft && childLocation == ChildLocation.Last;

                return new FormatYielder(this)
                {
                    topAncestorCacheForLeft = isLeftMostChild
                        ? this.topAncestorCacheForLeft
                        : (child ?? UnparsableAst.NonCalculated)
                };
            }
        }
示例#46
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated or thrown out.
        /// </exception>
        private static IEnumerable<UtokenBase> _YieldBetween(UnparsableAst self, FormatYielder formatYielder)
        {
            // NOTE: topAncestorCacheForLeft may get updated by GetUsedLeftsFromTopToBottomB

            UnparsableAst leftObject = GetLeftTerminalLeave(self);

            if (leftObject != null)
            {
                InsertedUtokens insertedUtokensBetween = formatYielder._GetUtokensBetween(leftObject, self);

                if (insertedUtokensBetween != InsertedUtokens.None)
                {
                    Unparser.tsUnparse.Debug("inserted utokens: {0}", insertedUtokensBetween);
                    yield return insertedUtokensBetween;
                }
            }
        }
示例#47
0
 public virtual BlockIndentation GetBlockIndentation(UnparsableAst leftTerminalLeaveIfAny, UnparsableAst target)
 {
     return BlockIndentation.IndentNotNeeded;
 }
示例#48
0
        private IEnumerable<UtokenBase> YieldIndentationRight(UnparsableAst self, ref BlockIndentation blockIndentation)
        {
            Unparser.tsUnparse.Debug("YieldIndentationRight");

            try
            {
                // NOTE: topAncestorCacheForLeft may get updated by YieldIndentation
                // NOTE: ToList is needed to fully evaluate the called function, so we can catch the exception
                return _YieldIndentation(self, ref blockIndentation, direction, formatYielder: this, left: false).ToList();
            }
            catch (NonCalculatedException)
            {
                // top left node or someone in the chain is non-calculated -> defer execution
                Debug.Assert(blockIndentation == BlockIndentation.ToBeSet || blockIndentation.IsDeferred());

                if (blockIndentation == BlockIndentation.ToBeSet)
                    blockIndentation = BlockIndentation.Defer();

                Debug.Assert(blockIndentation.IsDeferred());

                BlockIndentation _blockIndentation = blockIndentation;

                return new[]
                {
                    blockIndentation.RightDeferred = new DeferredUtokens(
                        () => _YieldIndentation(self, _blockIndentation, direction, formatYielder: this, left: false),
                        self: self,
                        helpMessage: "YieldIndentationRight",
                        helpCalculatedObject: _blockIndentation
                        )
                };
            }
        }
示例#49
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated.
        /// </exception>
        private static UnparsableAst GetLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder = null)
        {
            // NOTE: topAncestorCacheForLeft will not be changed if we have no formatter, that's why we use topAncestorForLeft + the static vs. instance behavior
            UnparsableAst leftTerminalLeave;

            if (formatYielder == null || !UnparsableAst.IsCalculated(formatYielder.topAncestorCacheForLeft))
            {
                leftTerminalLeave = CalculateLeftTerminalLeave(self, formatYielder);

                if (formatYielder != null)
                    formatYielder.leftTerminalLeaveCache = leftTerminalLeave;
            }
            else
            {
                leftTerminalLeave = formatYielder.leftTerminalLeaveCache;
                //Unparser.tsUnparse.Debug(formatter.leftTerminalLeaveCache != CalculateLeftTerminalLeave(self, formatter),
                //    "!!!!!!!! should be equal for {0}, but leftTerminalLeaveCache is '{1}' and calculated value is '{2}'", self, formatter.leftTerminalLeaveCache, CalculateLeftTerminalLeave(self, formatter));
                Debug.Assert(formatYielder.leftTerminalLeaveCache == CalculateLeftTerminalLeave(self, formatYielder));
            }

            return leftTerminalLeave;
        }
示例#50
0
 private static UnparsableAst CalculateLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder)
 {
     return GetLeftsFromTopToBottom(self, formatYielder).LastOrDefault();
 }
示例#51
0
 private static IEnumerable<BnfTerm> GetSelfAndAncestorsB(UnparsableAst self)
 {
     return GetSelfAndAncestors(self).Select(current => current.BnfTerm);
 }
示例#52
0
        private IEnumerable<UtokenBase> YieldBetween(UnparsableAst self)
        {
            Unparser.tsUnparse.Debug("YieldBetween");

            try
            {
                // NOTE: topAncestorCacheForLeft may get updated by _YieldBetween
                // NOTE: ToList is needed to fully evaluate the called function, so we can catch the exception
                return _YieldBetween(self, formatYielder: this).ToList();
            }
            catch (NonCalculatedException)
            {
                // top left node or someone in the chain is non-calculated -> defer execution

                return new[]
                {
                    new DeferredUtokens(
                        () => _YieldBetween(self, formatYielder: this),
                        self: self,
                        helpMessage: "YieldBetween"
                        )
                };
            }
        }
示例#53
0
 private static UnparsableAst CalculateLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder)
 {
     return(GetLeftsFromTopToBottom(self, formatYielder).LastOrDefault());
 }
示例#54
0
        private static UnparsableAst GetTopAncestorForLeft(UnparsableAst self, FormatYielder formatYielder = null)
        {
            // NOTE: topAncestorCacheForLeft will not be changed if we have no formatter, that's why we use topAncestorForLeft + the static vs. instance behavior
            UnparsableAst topAncestorForLeft;

            if (formatYielder == null || !UnparsableAst.IsCalculated(formatYielder.topAncestorCacheForLeft))
            {
                topAncestorForLeft = CalculateTopAncestorForLeft(self);

                if (formatYielder != null)
                    formatYielder.topAncestorCacheForLeft = topAncestorForLeft;
            }
            else
            {
                topAncestorForLeft = formatYielder.topAncestorCacheForLeft;
                //Unparser.tsUnparse.Debug(formatter.topAncestorCacheForLeft != CalculateTopAncestorForLeft(self),
                //    "!!!!!!!! should be equal for {0}, but topAncestorCacheForLeft is '{1}' and calculated value is '{2}'", self, formatter.topAncestorCacheForLeft, CalculateTopAncestorForLeft(self));
                Debug.Assert(formatYielder.topAncestorCacheForLeft == CalculateTopAncestorForLeft(self));
            }

            return topAncestorForLeft;
        }
示例#55
0
 private static UnparsableAst CalculateTopAncestorForLeft(UnparsableAst self)
 {
     return GetSelfAndAncestors(self).FirstOrDefault(current => current.LeftSibling != null);
 }
示例#56
0
        /// <exception cref="UnparsableAst.NonCalculatedException">
        /// If topLeft is non-calculated.
        /// </exception>
        private static IEnumerable<UnparsableAst> GetLeftsFromTopToBottom(UnparsableAst self, FormatYielder formatYielder = null)
        {
            UnparsableAst topAncestorForLeft = GetTopAncestorForLeft(self, formatYielder);

            return topAncestorForLeft != null
                ? Util.RecurseStopBeforeNull(topAncestorForLeft.LeftSibling, current => current.RightMostChild)
                : Enumerable.Empty<UnparsableAst>();
        }
示例#57
0
 private BlockIndentation _GetBlockIndentation(UnparsableAst leftIfAny, UnparsableAst target)
 {
     return formatter.GetBlockIndentation(leftIfAny, target);
 }
示例#58
0
 public virtual string[] GetDecoratedCommentTextLines(UnparsableAst owner, Comment comment)
 {
     if (comment.TextLines.Length > 1)
     {
         return comment.TextLines
             .Select((textLine, lineIndex) => lineIndex > 0 && comment.IsDecorated ? MultiLineCommentDecorator + textLine : textLine)
             .ToArray();
     }
     else
         return comment.TextLines;
 }
示例#59
0
 private static bool IsThrownOut(UnparsableAst unparsableAst)
 {
     return(object.ReferenceEquals(unparsableAst, ThrownOut));
 }
示例#60
0
 private static IEnumerable<UnparsableAst> GetSelfAndAncestors(UnparsableAst self)
 {
     return Util.RecurseStopBeforeNull(self, current => current.SyntaxParent);
 }