Ejemplo n.º 1
0
        public static IEnumerable <Utoken> ProcessControls(this IEnumerable <UtokenBase> utokens, IPostProcessHelper postProcessHelper)
        {
            var formatter = postProcessHelper.Formatter;

            int         indentLevel = 0;
            int         indentLevelForCurrentLine     = 0;
            Stack <int> storedIndentLevel             = new Stack <int>();
            bool        allowWhitespaceBetweenUtokens = true;
            UtokenBase  prevNotControlUtoken          = null;

            /*
             * We have to yield the indentation after consuming the last utoken (regardless of left-to-right or right-to-left unparse),
             * so we use an extra null utoken.
             *
             * e.g.: In case of right-to-left unparse if utokens enumerable is not empty and the last processed utoken (which is the leftmost utoken)
             * is not a line separator (which is the common case) then we didn't yielded the utokenindent for the last processed line
             * (which is the topmost line), so we yield it now when processing the extra null utoken.
             * */
            foreach (UtokenBase utoken in utokens.Concat((UtokenBase)null))
            {
                if (IsControl(utoken))
                {
                    UtokenControl utokenControl = (UtokenControl)utoken;

                    switch (utokenControl.kind)
                    {
                    case UtokenControl.Kind.IncreaseIndentLevel:
                        indentLevel++;
                        break;

                    case UtokenControl.Kind.DecreaseIndentLevel:
                        indentLevel--;
                        break;

                    case UtokenControl.Kind.SetIndentLevelToNone:
                        storedIndentLevel.Push(indentLevel);
                        indentLevel = 0;
                        break;

                    case UtokenControl.Kind.RestoreIndentLevel:
                        indentLevel = storedIndentLevel.Pop();
                        break;

                    case UtokenControl.Kind.NoWhitespace:
                        allowWhitespaceBetweenUtokens = false;
                        break;

                    default:
                        throw new InvalidOperationException(string.Format("Unknown UtokenControl '{0}'", utokenControl.kind));
                    }
                }
                else if (utoken == UtokenValueControl.NoWhitespace)
                {
                    allowWhitespaceBetweenUtokens = false;
                }
                else
                {
                    if (postProcessHelper.Direction == Unparser.Direction.RightToLeft && IsLineSeparator(utoken) && (formatter.IndentEmptyLines || !IsLineSeparator(prevNotControlUtoken)))
                    {
                        yield return(new UtokenIndent(indentLevelForCurrentLine));
                    }

                    indentLevelForCurrentLine = indentLevel;

                    if (postProcessHelper.Direction == Unparser.Direction.LeftToRight && IsLineSeparator(prevNotControlUtoken) && (formatter.IndentEmptyLines || !IsLineSeparator(utoken)))
                    {
                        yield return(new UtokenIndent(indentLevelForCurrentLine));
                    }

                    if (allowWhitespaceBetweenUtokens && prevNotControlUtoken != null && utoken != null && !IsWhitespace(prevNotControlUtoken) && !IsWhitespace(utoken))
                    {
                        yield return(UtokenWhitespace.WhiteSpaceBetweenUtokens());
                    }

                    if (utoken != null)
                    {
                        yield return((Utoken)utoken);
                    }

                    allowWhitespaceBetweenUtokens = true;
                    prevNotControlUtoken          = utoken;
                }
            }
        }