protected virtual void CheckForIndentStyleMismatch(UString indent1, UString indent2, Token next) { int common = System.Math.Min(indent1.Length, indent2.Length); indent1 = indent1.Substring(0, common); indent2 = indent2.Substring(0, common); if (!indent1.Equals(indent2)) { ErrorSink.Write(Severity.Warning, IndexToLine(next), "Indentation style changed on this line from {0} to {1}", LesNodePrinter.PrintLiteral(indent1.ToString()), LesNodePrinter.PrintLiteral(indent2.ToString())); } }
/// <summary>Expresses an EC# token as a string.</summary> /// <remarks>This code is incomplete. /// <para/> /// 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. /// </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(Loyc.Syntax.Les.LesNodePrinter.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(LesNodePrinter.PrintId(t.Value as Symbol ?? GSymbol.Empty)); case TT.Base: return("base"); case TT.This: return("this"); case TT.Literal: return(LesNodePrinter.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; 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)); } }
void GetPatternComponents(LNode pattern, out LNode varBinding, out bool refExistingVar, out LNode cmpExpr, out LNode isType, out LNode inRange, out VList <LNode> subPatterns, out VList <LNode> conditions) { bool haveSubPatterns = false; subPatterns = VList <LNode> .Empty; refExistingVar = pattern.AttrNamed(S.Ref) != null; conditions = VList <LNode> .Empty; while (pattern.Calls(S.And, 2)) { conditions.Add(pattern.Args.Last); pattern = pattern.Args[0]; } LNode cmpExprOrBinding = null; varBinding = cmpExpr = isType = inRange = null; for (int pass = 1; pass <= 3; pass++) { LNode inRange2 = inRange, isType2 = isType; { LNode patternL; if (pattern.Calls(CodeSymbols.In, 2) && (patternL = pattern.Args[0]) != null && (inRange = pattern.Args[1]) != null || pattern.Calls((Symbol)"in", 2) && (patternL = pattern.Args[0]) != null && (inRange = pattern.Args[1]) != null) { pattern = patternL; if (inRange2 != null) { _context.Write(Severity.Error, inRange2, "match-case does not support multiple 'in' operators"); } } else if (pattern.Calls(CodeSymbols.Is, 2) && (cmpExprOrBinding = pattern.Args[0]) != null && (isType = pattern.Args[1]) != null || pattern.Calls((Symbol)"is", 2) && (cmpExprOrBinding = pattern.Args[0]) != null && (isType = pattern.Args[1]) != null) { pattern = cmpExprOrBinding; if (isType2 != null) { _context.Write(Severity.Error, isType2, "match-case does not support multiple 'is' operators"); } } else if (pattern.Calls(CodeSymbols.Is, 1) && (isType = pattern.Args[0]) != null || pattern.Calls((Symbol)"is", 1) && (isType = pattern.Args[0]) != null) { if (isType2 != null) { _context.Write(Severity.Error, isType2, "match-case does not support multiple 'is' operators"); } goto doneAnalysis; } else if (pattern.Calls(CodeSymbols.DotDotDot, 2) || pattern.Calls(CodeSymbols.DotDot, 2) || pattern.Calls(CodeSymbols.DotDotDot, 1) || pattern.Calls(CodeSymbols.DotDot, 1)) { inRange = pattern; goto doneAnalysis; } else if (pattern.Calls(CodeSymbols.Tuple)) { subPatterns = pattern.Args; cmpExprOrBinding = null; } else { LNode target = pattern.Target; if (!haveSubPatterns && pattern.IsCall && (!target.IsId || target.AttrNamed(S.TriviaInParens) != null || (!target.HasSpecialName && LesNodePrinter.IsNormalIdentifier(target.Name)))) { haveSubPatterns = true; subPatterns = pattern.Args; pattern = pattern.Target; } else { cmpExprOrBinding = pattern; } } } } doneAnalysis: if (cmpExprOrBinding != null) { if (cmpExprOrBinding.Calls(S.Substitute, 1)) { varBinding = cmpExprOrBinding[0]; } else if (refExistingVar) { varBinding = cmpExprOrBinding; } else if ((varBinding ?? cmpExprOrBinding).IsIdNamed(__)) { cmpExprOrBinding = varBinding = null; } if (varBinding != null) { if (varBinding.AttrNamed(S.Ref) != null) { refExistingVar = true; varBinding = varBinding.WithoutAttrs(); } if (!varBinding.IsId) { _context.Write(Severity.Error, varBinding, "Invalid variable name in match-case: {0}", varBinding); varBinding = null; } } if (varBinding == null) { cmpExpr = cmpExprOrBinding; } } if (refExistingVar && varBinding == null) { refExistingVar = false; var got = cmpExprOrBinding ?? pattern; _context.Write(Severity.Warning, got, "'ref' expected a variable name (got `{0}`)", got); } }