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; } } }
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) }); } }
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 ) }); } }
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)); } }
/// <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>()); }
public bool Equals(UnparsableAst that) { return(object.ReferenceEquals(this, that) || !object.ReferenceEquals(that, null) && this.BnfTerm == that.BnfTerm && this.AstValue == that.AstValue); }
internal IDecoration GetDecoration(Utoken utoken) { UnparsableAst target = utoken is UtokenText ? ((UtokenText)utoken).Reference : null; return(GetDecoration(utoken, target)); }
private UnparsableAst GetParenthesis(ParenthesisKind parenthesisKind, UnparsableAst unparsableExpression) { BnfTerm parenthesis = parenthesisKind == ParenthesisKind.Left ? GetSurroundingParentheses().LeftParenthesis : GetSurroundingParentheses().RightParenthesis; return(new UnparsableAst(parenthesis, unparsableExpression.AstValue)); }
/// <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)); } }
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; }
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)); }
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); }
/// <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); }
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)); } }
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); }
/// <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); }
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); } }
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; }
/// <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); } } }
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); } } }
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()); } }
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); } }
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)); } }
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); }
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); }
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" ) }); } }
/// <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); }
internal void ResetMutableState() { topAncestorCacheForLeft = UnparsableAst.NonCalculated; }
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(); }
/// <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; }
protected override bool TryGetUtokensDirectly(IUnparser unparser, UnparsableAst self, out IEnumerable<UtokenValue> utokens) { utokens = null; return false; }
/// <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; }
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); } }
internal static bool IsCalculated(UnparsableAst unparsableAst) { return(!object.ReferenceEquals(unparsableAst, NonCalculated)); }
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; }
private InsertedUtokens _GetUtokensBetween(UnparsableAst leftTarget, UnparsableAst rightTarget) { return formatter.GetUtokensBetween(leftTarget, rightTarget) .SetKind(InsertedUtokens.Kind.Between) .SetAffected(leftTarget, rightTarget); }
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); }
/// <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); } }
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; } }
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; } }
public virtual InsertedUtokens GetUtokensBetween(UnparsableAst leftTerminalLeaveTarget, UnparsableAst rightTarget) { return InsertedUtokens.None; }
public virtual IDecoration GetDecoration(Utoken utoken, UnparsableAst target) { return Decoration.None; }
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); }
private static UnparsableAst CalculateTopAncestorForLeft(UnparsableAst self) { return(GetSelfAndAncestors(self).FirstOrDefault(current => current.LeftSibling != null)); }
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) }; } }
/// <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; } } }
public virtual BlockIndentation GetBlockIndentation(UnparsableAst leftTerminalLeaveIfAny, UnparsableAst target) { return BlockIndentation.IndentNotNeeded; }
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 ) }; } }
/// <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; }
private static UnparsableAst CalculateLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder) { return GetLeftsFromTopToBottom(self, formatYielder).LastOrDefault(); }
private static IEnumerable<BnfTerm> GetSelfAndAncestorsB(UnparsableAst self) { return GetSelfAndAncestors(self).Select(current => current.BnfTerm); }
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" ) }; } }
private static UnparsableAst CalculateLeftTerminalLeave(UnparsableAst self, FormatYielder formatYielder) { return(GetLeftsFromTopToBottom(self, formatYielder).LastOrDefault()); }
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; }
private static UnparsableAst CalculateTopAncestorForLeft(UnparsableAst self) { return GetSelfAndAncestors(self).FirstOrDefault(current => current.LeftSibling != null); }
/// <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>(); }
private BlockIndentation _GetBlockIndentation(UnparsableAst leftIfAny, UnparsableAst target) { return formatter.GetBlockIndentation(leftIfAny, target); }
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; }
private static bool IsThrownOut(UnparsableAst unparsableAst) { return(object.ReferenceEquals(unparsableAst, ThrownOut)); }
private static IEnumerable<UnparsableAst> GetSelfAndAncestors(UnparsableAst self) { return Util.RecurseStopBeforeNull(self, current => current.SyntaxParent); }