static void ToStringReal(IEnumerable <TokenExpression> subexpressions, MyIndentedTextWriter tw)
 {
     foreach (var subexpression in subexpressions)
     {
         ToStringReal(subexpression, tw);
     }
 }
        static string ToStringReal(TokenExpression ex)
        {
            if (ex == null)
            {
                return("");
            }
            StringBuilder        sb = new StringBuilder();
            StringWriter         sw = new StringWriter(sb);
            MyIndentedTextWriter tw = new MyIndentedTextWriter(sw);

            ToStringReal(ex, tw);
            return(sb.ToString());
        }
        static void ToStringReal(TokenExpression ex, MyIndentedTextWriter tw)
        {
            if (ex == null)
            {
                return;
            }
            switch (ex.TokenType)
            {
            default:
                if (!String.IsNullOrEmpty(ex.Token.Value) && ex.Token.Value != "...")
                {
                    tw.Write(ex.Token.Value);
                }
                if (ex.Subexpressions.Count > 0)
                {
                    tw.Write(" ");
                    ToStringReal(ex.Subexpressions, tw);
                }
                break;

            case TokenType.Array:
            case TokenType.AddressOf:
            case TokenType.At:
            case TokenType.Complement:
            case TokenType.Increment:
            case TokenType.Decrement:
                if (!String.IsNullOrEmpty(ex.Token.Value) && ex.Token.Value != "...")
                {
                    tw.Write(ex.Token.Value);
                }
                if (ex.Subexpressions.Count > 0)
                {
                    ToStringReal(ex.Subexpressions, tw);
                }
                break;

            case TokenType.Block:
                if (!tw.TabsPending)
                {
                    tw.WriteLine();
                }
                tw.WriteLine("{");
                tw.Indent++;
                ToStringReal(ex.Subexpressions, tw);
                tw.Indent--;
                if (!tw.TabsPending)
                {
                    tw.WriteLine();
                }
                tw.WriteLine("}");
                break;

            case TokenType.Statement:
                ToStringReal(ex.Subexpressions, tw);
                tw.WriteLine(";");
                break;

            case TokenType.StringLiteral:
                tw.Write(AssemblerProjectWriter.EscapeAndQuoteString(ex.Token.Value));
                break;

            case TokenType.CharLiteral:
            case TokenType.Message:
                tw.Write(AssemblerProjectWriter.EscapeAndQuoteMessage(ex.Token.Value));
                break;

            case TokenType.ArrayIndex:
                tw.Write("[");
                ToStringReal(ex.Subexpressions, tw);
                tw.Write("]");
                break;

            case TokenType.Assert:
                tw.Write("assert (");
                for (int i = 0; i < ex.Subexpressions.Count; i++)
                {
                    if (i != 0)
                    {
                        tw.Write(", ");
                    }
                    ToStringReal(ex.Subexpressions[i], tw);
                }
                tw.Write(")");
                break;

            case TokenType.For:
                tw.Write("for (");
                for (int i = 0; i < 3; i++)
                {
                    if (i != 0)
                    {
                        tw.Write("; ");
                    }
                    var subex = ex.Subexpressions.GetOrNull(i);
                    ToStringReal(subex, tw);
                }
                tw.WriteLine(")");
                ToStringReal(ex.Subexpressions.GetOrNull(3), tw);
                break;

            case TokenType.While:
                tw.Write("while (");
                ToStringReal(ex.Subexpressions.GetOrNull(0), tw);
                tw.WriteLine(")");
                ToStringReal(ex.Subexpressions.GetOrNull(1), tw);
                break;

            case TokenType.If:
                tw.Write("if (");
                ToStringReal(ex.Subexpressions.GetOrNull(0), tw);
                tw.WriteLine(")");
                ToStringReal(ex.Subexpressions.GetOrNull(1), tw);
                {
                    var subex = ex.Subexpressions.GetOrNull(2);
                    if (subex != null)
                    {
                        ToStringReal(subex, tw);
                    }
                }
                break;

            case TokenType.Switch:
                tw.Write("switch (");
                ToStringReal(ex.Subexpressions.GetOrNull(0), tw);
                tw.WriteLine(")");
                ToStringReal(ex.Subexpressions.Skip(1), tw);
                break;

            case TokenType.FunctionCall:
                ToStringReal(ex.Subexpressions.GetOrNull(0), tw);
                tw.Write("(");
                ToStringReal(ex.Subexpressions.Skip(1), tw);
                tw.Write(")");
                break;

            case TokenType.PostDecrement:
            case TokenType.PostIncrement:
                ToStringReal(ex.Subexpressions, tw);
                tw.Write(ex.Token.Value);
                break;

            //infix binary operators
            case TokenType.And:
            case TokenType.AndAssign:
            case TokenType.Assign:
            case TokenType.Colon:
            case TokenType.Comma:
            case TokenType.Divide:
            case TokenType.DivideAssign:
            case TokenType.Dot:
            case TokenType.EqualTo:
            case TokenType.LeftShift:
            case TokenType.LeftShiftAssign:
            case TokenType.LessThan:
            case TokenType.LessThanOrEqualTo:
            case TokenType.LogicalAnd:
            case TokenType.LogicalOr:
            case TokenType.Minus:
            case TokenType.MinusAssign:
            case TokenType.Modulo:
            case TokenType.ModuloAssign:
            case TokenType.Multiply:
            case TokenType.MultiplyAssign:
            case TokenType.NotEqualTo:
            case TokenType.Or:
            case TokenType.OrAssign:
            case TokenType.Plus:
            case TokenType.PlusAssign:
            case TokenType.QuestionMark:
            case TokenType.ReferenceAssign:
            case TokenType.ReferenceEqualTo:
            case TokenType.ReferenceNotEqualTo:
            case TokenType.ReferenceSwap:
            case TokenType.RightShift:
            case TokenType.RightShiftAssign:
            case TokenType.Xor:
            case TokenType.XorAssign:
                //output left side
                ToStringReal(ex.Subexpressions.GetOrNull(0), tw);

                if (ex.TokenType != TokenType.Comma && ex.TokenType != TokenType.Dot)
                {
                    tw.Write(" ");
                }

                if (String.IsNullOrEmpty(ex.Token.Value) || ex.Token.Value == "...")
                {
                    if (keywordTableInverse.ContainsKey(ex.TokenType))
                    {
                        tw.Write(keywordTableInverse[ex.TokenType]);
                    }
                }
                else
                {
                    tw.Write(ex.Token.Value);
                }
                if (ex.TokenType != TokenType.Dot)
                {
                    tw.Write(" ");
                }

                ToStringReal(ex.Subexpressions.Skip(1), tw);
                break;
            }



            //foreach (var ex in exBase.GetAllSubexpressionsRecursive())
            //{
            //    switch (ex.TokenType)
            //    {
            //        case TokenType.And:
            //            case TokenType.

            //        default:
            //            sb.Append(ex.Token.Value);
            //            break;
            //    }
            //}
            //return sb.ToString();
        }