示例#1
0
        static VList <LNode> AddLineDirectives(VList <LNode> nodes, bool stmtContext, ref int sourceLine_)
        {
            int sourceLine = sourceLine_;

            nodes = nodes.SmartSelect(node => {
                if (stmtContext && sourceLine > 0 && node.AttrNamed(S.TriviaAppendStatement) == null)
                {
                    sourceLine++;                     // printer will print a newline by default
                }
                int explicitNewlines = node.Attrs.Count(n => n.IsIdNamed(S.TriviaNewline));
                sourceLine          += explicitNewlines;

                // Generate line directive if necessary; to avoid excess
                // clutter, don't consider emit #line directives within an expression.
                string lineDirective = null;
                if (stmtContext || explicitNewlines != 0)
                {
                    if (node.Range.Source is EmptySourceFile || string.IsNullOrEmpty(node.Range.Source.FileName))
                    {
                        // synthetic code: no source location
                        if (sourceLine != -1)
                        {
                            sourceLine    = -1;
                            lineDirective = "#line default";
                        }
                    }
                    else
                    {
                        var start = node.Range.Start;
                        if (sourceLine != start.Line)
                        {
                            sourceLine    = start.Line;
                            lineDirective = "#line " + start.Line + " " + EcsNodePrinter.PrintString(start.FileName, '"');
                        }
                    }
                }

                int sourceLineWas = sourceLine;

                if (node.Name.Name.StartsWith("#") && node.ArgCount > 1)
                {
                    // For some special calls like #if, #while, and #doWhile,
                    // printer might print newlines in places we don't know about,
                    // so erase our knowledge of what the current line is.
                    if (sourceLine > 0)
                    {
                        sourceLine = int.MinValue;
                    }
                }

                // Process children
                node = node.WithAttrs(AddLineDirectives(node.Attrs, false, ref sourceLine));
                if (node.IsCall)
                {
                    node = node.WithArgs(AddLineDirectives(node.Args, node.Calls(S.Braces), ref sourceLine));
                }

                if (sourceLine > 0)
                {
                    sourceLine += node.GetTrailingTrivia().Count(n => n.IsIdNamed(S.TriviaNewline));
                }

                // Finally, add a line directive if requested.
                if (lineDirective != null)
                {
                    var trivia = F.Trivia(S.TriviaCsPPRawText, lineDirective);
                    if (!node.Attrs.Contains(trivia))
                    {
                        // Trivia tends not to be included in the source range so adding #line
                        // before trivia is generally wrong, while adding #line after attributes
                        // tends to be wrong too. Sigh. Search for a good location to insert...
                        // unless inserting #line default which we can just put at the beginning
                        int insertIndex = 0;
                        if (sourceLineWas > 0)
                        {
                            insertIndex = node.Attrs.IndexWhere(n => n.Range.Start.Line == sourceLineWas && n.Range.Source == node.Range.Source);
                            if (insertIndex == -1)
                            {
                                insertIndex = node.Attrs.Count;
                            }
                        }
                        node = node.WithAttrs(node.Attrs.Insert(insertIndex, trivia));
                    }
                }

                return(node);
            });
            sourceLine_ = sourceLine;
            return(nodes);
        }
示例#2
0
文件: TokenType.cs 项目: Shaykh/Loyc
        /// <summary>Expresses an EC# token as a string.</summary>
        /// <remarks>Note that some Tokens do not contain enough information to
        /// reconstruct a useful token string, e.g. comment tokens do not store the
        /// comment but merely contain the location of the comment in the source code.
        /// For performance reasons, a <see cref="Token"/> does not have a reference
        /// to its source file, so this method cannot return the original string.
        /// <para/>
        /// The results are undefined if the token was not produced by <see cref="EcsLexer"/>.
        /// </remarks>
        public static string ToString(Token t)
        {
            StringBuilder sb = new StringBuilder();

            if (t.Kind == TokenKind.Operator || t.Kind == TokenKind.Assignment || t.Kind == TokenKind.Dot)
            {
                if (t.Type() == TT.BQString)
                {
                    return(EcsNodePrinter.PrintString((t.Value ?? "").ToString(), '`', false));
                }
                string value = (t.Value ?? "(null)").ToString();
                return(value);
            }
            switch (t.Type())
            {
            case TT.EOF: return("/*EOF*/");

            case TT.Spaces: return(" ");

            case TT.Newline: return("\n");

            case TT.SLComment: return("//\n");

            case TT.MLComment: return("/**/");

            case TT.Shebang: return("#!" + (t.Value ?? "").ToString() + "\n");

            case TT.Id:
            case TT.ContextualKeyword:
                return(EcsNodePrinter.PrintId(t.Value as Symbol ?? GSymbol.Empty));

            case TT.@base: return("base");

            case TT.@this: return("this");

            case TT.Number:
            case TT.String:
            case TT.SQString:
            case TT.Symbol:
            case TT.OtherLit:
                return(EcsNodePrinter.PrintLiteral(t.Value, t.Style));

            case TT.Comma: return(",");

            case TT.Semicolon: return(";");

            case TT.LParen: return("(");

            case TT.RParen: return(")");

            case TT.LBrack: return("[");

            case TT.RBrack: return("]");

            case TT.LBrace: return("{");

            case TT.RBrace: return("}");

            case TT.AttrKeyword:
                string value = (t.Value ?? "(null)").ToString();
                return(value);

            case TT.TypeKeyword:
                Symbol valueSym = (t.Value as Symbol) ?? GSymbol.Empty;
                string result;
                if (EcsNodePrinter.TypeKeywords.TryGetValue(valueSym, out result))
                {
                    return(result);
                }
                else
                {
                    Debug.Fail("Unexpected value for " + t.Type());
                    return((t.Value ?? "(null)").ToString());
                }

            case TT.@break:     return("break");

            case TT.@case:          return("case");

            case TT.@checked:       return("checked");

            case TT.@class:         return("class");

            case TT.@continue:      return("continue");

            case TT.@default:       return("default");

            case TT.@delegate:      return("delegate");

            case TT.@do:            return("do");

            case TT.@enum:          return("enum");

            case TT.@event:         return("event");

            case TT.@fixed:         return("fixed");

            case TT.@for:           return("for");

            case TT.@foreach:       return("foreach");

            case TT.@goto:          return("goto");

            case TT.@if:            return("if");

            case TT.@interface:     return("interface");

            case TT.@lock:          return("lock");

            case TT.@namespace:     return("namespace");

            case TT.@return:        return("return");

            case TT.@struct:        return("struct");

            case TT.@switch:        return("switch");

            case TT.@throw:         return("throw");

            case TT.@try:           return("try");

            case TT.@unchecked:     return("unchecked");

            case TT.@using:         return("using");

            case TT.@while:         return("while");

            case TT.@operator:  return("operator");

            case TT.@sizeof:    return("sizeof");

            case TT.@typeof:    return("typeof");

            case TT.@else:      return("else");

            case TT.@catch:     return("catch");

            case TT.@finally:       return("finally");

            case TT.@in:            return("in");

            case TT.@as:            return("as");

            case TT.@is:            return("is");

            case TT.@new:           return("new");

            case TT.@out:           return("out");

            case TT.@stackalloc: return("stackalloc");

            case TT.PPif: return("#if");

            case TT.PPelse: return("#else");

            case TT.PPelif: return("#elif");

            case TT.PPendif: return("#endif");

            case TT.PPdefine: return("#define");

            case TT.PPundef: return("#undef");

            case TT.PPwarning: return("#warning" + t.Value);

            case TT.PPerror: return("#error" + t.Value);

            case TT.PPnote: return("#note" + t.Value);

            case TT.PPline: return("#line");

            case TT.PPregion: return("#region" + t.Value);

            case TT.PPendregion: return("#endregion");

            case TT.PPpragma: return("#pragma");

            case TT.PPignored: return((t.Value ?? "").ToString());

            default:
                return(string.Format("@`unknown token 0x{0:X4}`", t.TypeInt));
            }
        }
示例#3
0
        /// <summary>Expresses an EC# token as a string.</summary>
        /// <remarks>Note that some Tokens do not contain enough information to
        /// reconstruct a useful token string, e.g. comment tokens do not store the
        /// comment but merely contain the location of the comment in the source code.
        /// For performance reasons, a <see cref="Token"/> does not have a reference
        /// to its source file, so this method cannot return the original string.
        /// <para/>
        /// The results are undefined if the token was not produced by <see cref="EcsLexer"/>.
        /// </remarks>
        public static string ToString(Token t, ICharSource sourceCode)
        {
            if (sourceCode != null && t.EndIndex <= sourceCode.Count)
            {
                return(sourceCode.Slice(t.StartIndex, t.Length).ToString());
            }

            StringBuilder sb = new StringBuilder();

            if (t.Kind == TokenKind.Operator || t.Kind == TokenKind.Assignment || t.Kind == TokenKind.Dot)
            {
                if (t.Type() == TT.BQString)
                {
                    return(EcsNodePrinter.PrintString((t.Value ?? "").ToString(), '`', false));
                }
                string value = (t.Value ?? "(null)").ToString();
                return(value);
            }
            switch (t.Type())
            {
            case TT.EOF: return("/*EOF*/");

            case TT.Spaces: return(" ");

            case TT.Newline: return("\n");

            case TT.SLComment: return("//\n");

            case TT.MLComment: return("/**/");

            case TT.Shebang: return("#!" + (t.Value ?? "").ToString() + "\n");

            case TT.Id:
            case TT.ContextualKeyword:
            case TT.LinqKeyword:
                var mode = (t.Style & NodeStyle.Operator) != 0 ? EcsNodePrinter.IdPrintMode.Operator :
                           (t.Style & NodeStyle.VerbatimId) != 0 ? EcsNodePrinter.IdPrintMode.Verbatim : EcsNodePrinter.IdPrintMode.Normal;
                return(EcsNodePrinter.PrintId(t.Value as Symbol ?? GSymbol.Empty, mode));

            case TT.Base: return("base");

            case TT.This: return("this");

            case TT.Literal:
                return(EcsNodePrinter.PrintLiteral(t.Value, t.Style));

            case TT.Comma: return(",");

            case TT.Semicolon: return(";");

            case TT.LParen: return("(");

            case TT.RParen: return(")");

            case TT.LBrack: return("[");

            case TT.RBrack: return("]");

            case TT.LBrace: return("{");

            case TT.RBrace: return("}");

            case TT.AttrKeyword:
                string value = (t.Value ?? "(null)").ToString();
                return(value);

            case TT.TypeKeyword:
                Symbol valueSym = (t.Value as Symbol) ?? GSymbol.Empty;
                string result;
                if (EcsFacts.TypeKeywords.TryGetValue(valueSym, out result))
                {
                    return(result);
                }
                else
                {
                    Debug.Fail("Unexpected value for " + t.Type());
                    return((t.Value ?? "(null)").ToString());
                }

            case TT.CheckedOrUnchecked:
                Debug.Assert(LNode.IsSpecialName((Symbol)t.Value));
                return(((Symbol)t.Value).Name.Substring(1));

            case TT.Break:       return("break");

            case TT.Case:        return("case");

            case TT.Class:       return("class");

            case TT.Continue:    return("continue");

            case TT.Default:     return("default");

            case TT.Delegate:    return("delegate");

            case TT.Do:          return("do");

            case TT.Enum:        return("enum");

            case TT.Event:       return("event");

            case TT.Fixed:       return("fixed");

            case TT.For:         return("for");

            case TT.Foreach:     return("foreach");

            case TT.Goto:        return("goto");

            case TT.If:          return("if");

            case TT.Interface:   return("interface");

            case TT.Lock:        return("lock");

            case TT.Namespace:   return("namespace");

            case TT.Return:      return("return");

            case TT.Struct:      return("struct");

            case TT.Switch:      return("switch");

            case TT.Throw:       return("throw");

            case TT.Try:         return("try");

            case TT.Using:       return("using");

            case TT.While:       return("while");

            case TT.Operator:    return("operator");

            case TT.Sizeof:      return("sizeof");

            case TT.Typeof:      return("typeof");

            case TT.Else:        return("else");

            case TT.Catch:       return("catch");

            case TT.Finally:     return("finally");

            case TT.In:          return("in");

            case TT.As:          return("as");

            case TT.Is:          return("is");

            case TT.New:         return("new");

            case TT.Out:         return("out");

            case TT.Stackalloc:  return("stackalloc");

            case TT.PPif: return("#if");

            case TT.PPelse: return("#else");

            case TT.PPelif: return("#elif");

            case TT.PPendif: return("#endif");

            case TT.PPdefine: return("#define");

            case TT.PPundef: return("#undef");

            case TT.PPwarning: return("#warning" + t.Value);

            case TT.PPerror: return("#error" + t.Value);

            case TT.PPnote: return("#note" + t.Value);

            case TT.PPline: return("#line");

            case TT.PPregion: return("#region" + t.Value);

            case TT.PPendregion: return("#endregion");

            case TT.PPpragma: return("#pragma");

            case TT.PPignored: return((t.Value ?? "").ToString());

            default:
                return(string.Format("@`unknown token 0x{0:X4}`", t.TypeInt));
            }
        }