From 9de8da3c937c53c23d11e0d3a5af15123c65ebec Mon Sep 17 00:00:00 2001 From: David Piepgrass Date: Sun, 4 Dec 2016 10:26:01 +0800 Subject: [PATCH] Tweaks. - Fix .NET 3.5 build. - Added LES3 syntax highlighting, but it's glitchy. --- .../ExtensionMethods/LCExtensions.cs | 12 +- .../Interfaces/Queue interfaces.cs | 8 - Core/Loyc.Essentials/Compatibility/Enum.cs | 155 +++++++++++++ Core/Loyc.Essentials/Loyc.Essentials.csproj | 1 + Core/Loyc.Syntax/LES/Les2Printer.cs | 6 +- Core/Loyc.Syntax/LES/Les3.cs | 7 +- Core/Loyc.Syntax/LES/Les3Lexer.ecs | 13 +- Core/Loyc.Syntax/LES/Les3Lexer.out.cs | 204 ++++++++--------- Core/Loyc.Syntax/LES/Les3Parser.out.cs | 4 +- Core/Loyc.Syntax/LES/Les3PrettyPrinter.cs | 16 +- Core/Loyc.Syntax/LNodes/ILNode.cs | 2 +- Core/Loyc.Syntax/LNodes/ILNodePrinter.cs | 2 +- .../LNodes/ILNodePrintingOptions.cs | 3 +- Core/Loyc.Syntax/LNodes/LNode.cs | 12 +- Core/Loyc.Syntax/LeMP/IMacroContext.cs | 3 - Core/Loyc.Syntax/PrinterState.cs | 2 +- .../GoInterface tests.csproj | 0 .../GoInterface tests.sln | 0 .../GoInterface test project/Program.cs | 0 .../GoInterface test project/app.config | 0 .../nunit.framework.dll | Bin .../GoInterfaceBenchmark.cs | 0 Main/LeMP.StdMacros/ReplaceMacro.cs | 2 +- .../LoycExtensionForVs/BraceMatchingTagger.cs | 3 +- .../LoycExtensionForVs/EcsSyntaxForVS.cs | 2 +- .../{LesSyntaxForVS.cs => Les2SyntaxForVs.cs} | 38 ++-- .../LoycExtensionForVs/Les3SyntaxForVS.cs | 212 ++++++++++++++++++ .../LoycSyntaxForVS2010.csproj | 3 +- 28 files changed, 534 insertions(+), 176 deletions(-) create mode 100644 Core/Loyc.Essentials/Compatibility/Enum.cs rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterface test project/GoInterface tests.csproj (100%) rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterface test project/GoInterface tests.sln (100%) rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterface test project/Program.cs (100%) rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterface test project/app.config (100%) rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterface test project/nunit.framework.dll (100%) rename Core/{Loyc.Essentials/Utilities => Loyc.Utilities}/GoInterfaceBenchmark.cs (100%) rename Visual Studio Integration/LoycExtensionForVs/{LesSyntaxForVS.cs => Les2SyntaxForVs.cs} (88%) create mode 100644 Visual Studio Integration/LoycExtensionForVs/Les3SyntaxForVS.cs diff --git a/Core/Loyc.Essentials/Collections/ExtensionMethods/LCExtensions.cs b/Core/Loyc.Essentials/Collections/ExtensionMethods/LCExtensions.cs index 9418b3e6b..4e0d86396 100644 --- a/Core/Loyc.Essentials/Collections/ExtensionMethods/LCExtensions.cs +++ b/Core/Loyc.Essentials/Collections/ExtensionMethods/LCExtensions.cs @@ -73,23 +73,23 @@ public static IIterable AsIterable(this IEnumerable list) public static IReadOnlyCollection UpCast(this IReadOnlyCollection source) where T : class, TResult { - #if DotNet4 || DotNet4_5 - return source; - #else + #if DotNet2 || DotNet3 if (source == null) return null; return new UpCastSource(source); + #else + return source; #endif } public static IListSource UpCast(this IListSource source) where T : class, TResult { - #if DotNet4 || DotNet4_5 - return source; - #else + #if DotNet2 || DotNet3 if (source == null) return null; return new UpCastListSource(source); + #else + return source; #endif } diff --git a/Core/Loyc.Essentials/Collections/Interfaces/Queue interfaces.cs b/Core/Loyc.Essentials/Collections/Interfaces/Queue interfaces.cs index 2a3b36dde..f1b2a848c 100644 --- a/Core/Loyc.Essentials/Collections/Interfaces/Queue interfaces.cs +++ b/Core/Loyc.Essentials/Collections/Interfaces/Queue interfaces.cs @@ -5,11 +5,7 @@ namespace Loyc.Collections { /// Represents a collection that accepts a sequence of items. - #if DotNet4 || DotNet4_5 public interface IPush - #else - public interface IPush - #endif { void Push(T item); } @@ -19,11 +15,7 @@ public interface IPush /// Push/Pop methods that throw an exception on failure, and /// TryPush/TryPop methods that don't require a "ref" argument, are /// available as extension methods. - #if DotNet4 || DotNet4_5 public interface IPop - #else - public interface IPop - #endif { T TryPop(out bool isEmpty); T TryPeek(out bool isEmpty); diff --git a/Core/Loyc.Essentials/Compatibility/Enum.cs b/Core/Loyc.Essentials/Compatibility/Enum.cs new file mode 100644 index 000000000..3d88dad8c --- /dev/null +++ b/Core/Loyc.Essentials/Compatibility/Enum.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Loyc.Compatibility +{ + /// Implements Enum.TryParse in .NET 3.5 + public class EnumStatic + { + private static readonly char[] FlagDelimiter = new [] { ',' }; + + #if DotNet2 || DotNet3 + /// Implements Enum.TryParse in .NET 3.5 + /// By Herman Schoenfeld + public static bool TryParse(string value, out TEnum result) where TEnum : struct + { + if (string.IsNullOrEmpty(value)) { + result = default(TEnum); + return false; + } + + var typeofEnum = typeof(TEnum); + + result = default(TEnum); + + // Try to parse the value directly + if (Enum.IsDefined(typeofEnum, value)) { + result = (TEnum)Enum.Parse(typeofEnum, value); + return true; + } + + // Get some info on enum + var enumValues = Enum.GetValues(typeofEnum); + if (enumValues.Length == 0) + return false; // probably can't happen as you cant define empty enum? + var enumTypeCode = Type.GetTypeCode(enumValues.GetValue(0).GetType()); + + // Try to parse it as a flag + if (value.IndexOf(',') != -1) { + if (!Attribute.IsDefined(typeofEnum, typeof(FlagsAttribute))) + return false; // value has flags but enum is not flags + + // todo: cache this for efficiency + var enumInfo = new Dictionary(); + var enumNames = Enum.GetNames(typeofEnum); + for (var i = 0; i < enumNames.Length; i++) + enumInfo.Add(enumNames[i], enumValues.GetValue(i)); + + ulong retVal = 0; + foreach(var name in value.Split(FlagDelimiter)) { + var trimmedName = name.Trim(); + if (!enumInfo.ContainsKey(trimmedName)) + return false; // Enum has no such flag + + var enumValueObject = enumInfo[trimmedName]; + ulong enumValueLong; + switch (enumTypeCode) { + case TypeCode.Byte: + enumValueLong = (byte)enumValueObject; + break; + case TypeCode.SByte: + enumValueLong = (byte)((sbyte)enumValueObject); + break; + case TypeCode.Int16: + enumValueLong = (ushort)((short)enumValueObject); + break; + case TypeCode.Int32: + enumValueLong = (uint)((int)enumValueObject); + break; + case TypeCode.Int64: + enumValueLong = (ulong)((long)enumValueObject); + break; + case TypeCode.UInt16: + enumValueLong = (ushort)enumValueObject; + break; + case TypeCode.UInt32: + enumValueLong = (uint)enumValueObject; + break; + case TypeCode.UInt64: + enumValueLong = (ulong)enumValueObject; + break; + default: + return false; // should never happen + } + retVal |= enumValueLong; + } + result = (TEnum)Enum.ToObject(typeofEnum, retVal); + return true; + } + + // the value may be a number, so parse it directly + switch (enumTypeCode) { + case TypeCode.SByte: + sbyte sb; + if (!SByte.TryParse(value, out sb)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, sb); + break; + case TypeCode.Byte: + byte b; + if (!Byte.TryParse(value, out b)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, b); + break; + case TypeCode.Int16: + short i16; + if (!Int16.TryParse(value, out i16)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, i16); + break; + case TypeCode.UInt16: + ushort u16; + if (!UInt16.TryParse(value, out u16)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, u16); + break; + case TypeCode.Int32: + int i32; + if (!Int32.TryParse(value, out i32)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, i32); + break; + case TypeCode.UInt32: + uint u32; + if (!UInt32.TryParse(value, out u32)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, u32); + break; + case TypeCode.Int64: + long i64; + if (!Int64.TryParse(value, out i64)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, i64); + break; + case TypeCode.UInt64: + ulong u64; + if (!UInt64.TryParse(value, out u64)) + return false; + result = (TEnum)Enum.ToObject(typeofEnum, u64); + break; + default: + return false; // should never happen + } + + return true; + } + #else + public static bool TryParse(string value, out TEnum result) where TEnum : struct + { + return Enum.TryParse(value, out result); + } + #endif + } +} diff --git a/Core/Loyc.Essentials/Loyc.Essentials.csproj b/Core/Loyc.Essentials/Loyc.Essentials.csproj index c2e60d023..f340bf801 100644 --- a/Core/Loyc.Essentials/Loyc.Essentials.csproj +++ b/Core/Loyc.Essentials/Loyc.Essentials.csproj @@ -166,6 +166,7 @@ SelectListSource.ecs + diff --git a/Core/Loyc.Syntax/LES/Les2Printer.cs b/Core/Loyc.Syntax/LES/Les2Printer.cs index 717aca5ab..ab8c8dd87 100644 --- a/Core/Loyc.Syntax/LES/Les2Printer.cs +++ b/Core/Loyc.Syntax/LES/Les2Printer.cs @@ -454,7 +454,7 @@ public static string PrintString(string text, char quoteType, bool tripleQuoted) /// Returns true if the given symbol can be printed as a /// normal identifier, without an "@" prefix. Note: identifiers - /// starting with "#" still count as normal; call + /// starting with "#" still count as normal; call /// to detect this. public static bool IsNormalIdentifier(Symbol name) { @@ -686,8 +686,8 @@ public Les2PrinterOptions(ILNodePrinterOptions options) /// Causes comments and spaces to be printed as attributes in order /// to ensure faithful round-trip parsing. By default, only "raw text" and /// unrecognized trivia is printed this way. Note: #trivia_inParens is - /// always printed as parentheses, and has - /// no effect when this flag is true. + /// always printed as parentheses, and + /// has no effect when this flag is true. public override bool PrintTriviaExplicitly { get { return base.PrintTriviaExplicitly; } set { base.PrintTriviaExplicitly = value; } } /// When an argument to a method or macro has the value @``, diff --git a/Core/Loyc.Syntax/LES/Les3.cs b/Core/Loyc.Syntax/LES/Les3.cs index 21d045cee..6eec91d2d 100644 --- a/Core/Loyc.Syntax/LES/Les3.cs +++ b/Core/Loyc.Syntax/LES/Les3.cs @@ -13,10 +13,12 @@ using System.Diagnostics; using System.Numerics; using Loyc.Collections.Impl; +using System.ComponentModel; namespace Loyc.Syntax.Les { - partial class Les3Lexer : Les2Lexer + [EditorBrowsable(EditorBrowsableState.Never)] // used only by syntax highlighter + public partial class Les3Lexer : Les2Lexer { // When using the Loyc libraries, `BaseLexer` and `BaseILexer` read character // data from an `ICharSource`, which the string wrapper `UString` implements. @@ -248,7 +250,8 @@ void PrintErrorIfTypeMarkerIsKeywordLiteral(object boolOrNull) } } - partial class Les3Parser : Les2Parser + [EditorBrowsable(EditorBrowsableState.Never)] // used only by syntax highlighter + public partial class Les3Parser : Les2Parser { //LNodeFactory F; diff --git a/Core/Loyc.Syntax/LES/Les3Lexer.ecs b/Core/Loyc.Syntax/LES/Les3Lexer.ecs index d039464f1..890dded82 100644 --- a/Core/Loyc.Syntax/LES/Les3Lexer.ecs +++ b/Core/Loyc.Syntax/LES/Les3Lexer.ecs @@ -121,12 +121,6 @@ public partial class Les3Lexer // Identifiers and named literals ------------------------------------------ - [inline] extern token IdStartChar : '_'|'a'..'z'|'A'..'Z' ; - - private NormalId : - IdStartChar - greedy(IdStartChar | '#' | '0'..'9' | '\'' &!("''"))*; - private token Id returns [object result] : {object boolOrNull = NoValue.Value;} idtext:IdCore[ref boolOrNull] @@ -140,6 +134,13 @@ public partial class Les3Lexer )? {return boolOrNull != NoValue.Value ? boolOrNull : IdToSymbol(idtext);}; + // LES3 might not officially treat # as an identifier character, but it's handy for now + [inline] extern token IdStartChar : '_'|'a'..'z'|'A'..'Z'|'#' ; + + private NormalId : + IdStartChar + greedy(IdStartChar | '0'..'9' | '\'' &!("''"))*; + private token IdCore[ref object boolOrNull] returns [UString result] : ( BQString {$result = ParseStringCore(false);} | NormalId { diff --git a/Core/Loyc.Syntax/LES/Les3Lexer.out.cs b/Core/Loyc.Syntax/LES/Les3Lexer.out.cs index e43997208..bcbd00238 100644 --- a/Core/Loyc.Syntax/LES/Les3Lexer.out.cs +++ b/Core/Loyc.Syntax/LES/Les3Lexer.out.cs @@ -148,6 +148,7 @@ object MLComment() // line 37 return WhitespaceTag.Value; } + static readonly HashSet Number_set0 = NewSetOfRanges('#', '#', 'A', 'Z', '_', '_', 'a', 'z'); object Number() { @@ -187,7 +188,7 @@ object Number() la1 = LA(1); if (!(la1 == -1 || la1 == '\n' || la1 == '\r')) goto matchIdCore; - } else if (la0 >= 'A' && la0 <= 'Z' || la0 == '_' || la0 >= 'a' && la0 <= 'z') + } else if (Number_set0.Contains(la0)) goto matchIdCore; break; matchIdCore: @@ -675,40 +676,16 @@ object SQOperator() // line 120 return ParseNormalOp(); } - static readonly HashSet NormalId_set0 = NewSetOfRanges('A', 'Z', '_', '_', 'a', 'z'); - - void NormalId() - { - int la0; - Match(NormalId_set0); - // Line 128: greedy( [A-Z_a-z] | [#] | [0-9] | ['] &!(['] [']) )* - for (;;) { - la0 = LA0; - if (la0 >= 'A' && la0 <= 'Z' || la0 == '_' || la0 >= 'a' && la0 <= 'z') - Skip(); - else if (la0 == '#') - Skip(); - else if (la0 >= '0' && la0 <= '9') - Skip(); - else if (la0 == '\'') { - if (!Try_NormalId_Test0(1)) - Skip(); - else - break; - } else - break; - } - } object Id() { int la0, la1; UString idtext = default(UString); object value = default(object); - // line 131 + // line 125 object boolOrNull = NoValue.Value; idtext = IdCore(ref boolOrNull); - // Line 133: ((TQString / DQString))? + // Line 127: ((TQString / DQString))? do { la0 = LA0; if (la0 == '"') @@ -721,10 +698,10 @@ object Id() break; match1: { - var old_startPosition_0 = _startPosition; + var old_startPosition_10 = _startPosition; try { _startPosition = InputPosition; - // Line 134: (TQString / DQString) + // Line 128: (TQString / DQString) la0 = LA0; if (la0 == '"') { la1 = LA(1); @@ -734,32 +711,53 @@ object Id() value = DQString(); } else value = TQString(); - // line 136 + // line 130 _type = TT.Literal; PrintErrorIfTypeMarkerIsKeywordLiteral(boolOrNull); return _value = ParseLiteral2(idtext, value.ToString(), false); } finally { - _startPosition = old_startPosition_0; + _startPosition = old_startPosition_10; } } } while (false); - // line 141 + // line 135 return boolOrNull != NoValue.Value ? boolOrNull : IdToSymbol(idtext); } + void NormalId() + { + int la0; + Match(Number_set0); + // Line 142: greedy( [#A-Z_a-z] | [0-9] | ['] &!(['] [']) )* + for (;;) { + la0 = LA0; + if (Number_set0.Contains(la0)) + Skip(); + else if (la0 >= '0' && la0 <= '9') + Skip(); + else if (la0 == '\'') { + if (!Try_NormalId_Test0(1)) + Skip(); + else + break; + } else + break; + } + } + UString IdCore(ref object boolOrNull) { int la0; UString result = default(UString); - // Line 144: (BQString | NormalId) + // Line 145: (BQString | NormalId) la0 = LA0; if (la0 == '`') { BQString(); - // line 144 + // line 145 result = ParseStringCore(false); } else { NormalId(); - // line 146 + // line 147 result = Text(); if (result == "true") { _type = TT.Literal; @@ -788,7 +786,7 @@ object SpecialLiteral() Skip(); Skip(); LettersOrPunc(); - // Line 157: (LettersOrPunc)* + // Line 158: (LettersOrPunc)* for (;;) { la0 = LA0; if (SQOperator_set0.Contains(la0)) @@ -796,7 +794,7 @@ object SpecialLiteral() else break; } - // line 157 + // line 158 return ParseAtAtLiteral(Text()); } @@ -805,8 +803,8 @@ object Shebang() int la0; Check(InputPosition == 0, "InputPosition == 0"); Skip(); - Match('!'); - // Line 162: ([^\$\n\r])* + Skip(); + // Line 163: ([^\$\n\r])* for (;;) { la0 = LA0; if (!(la0 == -1 || la0 == '\n' || la0 == '\r')) @@ -814,11 +812,11 @@ object Shebang() else break; } - // Line 162: (Newline)? + // Line 163: (Newline)? la0 = LA0; if (la0 == '\n' || la0 == '\r') Newline(); - // line 163 + // line 164 return WhitespaceTag.Value; } @@ -826,7 +824,7 @@ public override Maybe NextToken() { int la0, la1, la2, la3; object value = default(object); - // Line 168: (Spaces / &{InputPosition == _lineStartAt} [.] [\t ] => DotIndent)? + // Line 169: (Spaces / &{InputPosition == _lineStartAt} [.] [\t ] => DotIndent)? la0 = LA0; if (la0 == '\t' || la0 == ' ') Spaces(); @@ -837,20 +835,24 @@ public override Maybe NextToken() DotIndent(); } } - // line 170 + // line 171 _startPosition = InputPosition; _style = 0; if (LA0 == -1) { return NoValue.Value; } - // Line 176: ( Shebang / SpecialLiteral / [`] => Id / Id / Newline / SLComment / MLComment / Number / TQString / DQString / SQString / SQOperator / ['] ['] / [,] / [;] / [(] / [)] / [[] / [\]] / [{] / [}] / ['] [{] / [@] [@] [{] / [@] / Operator ) + // Line 177: ( Shebang / SpecialLiteral / [`] => Id / Id / Newline / SLComment / MLComment / Number / TQString / DQString / SQString / SQOperator / ['] ['] / [,] / [;] / [(] / [)] / [[] / [\]] / [{] / [}] / ['] [{] / [@] [@] [{] / [@] / Operator ) do { switch (LA0) { case '#': { - // line 176 - _type = TT.Shebang; - value = Shebang(); + la1 = LA(1); + if (la1 == '!') { + // line 177 + _type = TT.Shebang; + value = Shebang(); + } else + goto matchId; } break; case '@': @@ -859,11 +861,11 @@ public override Maybe NextToken() if (la1 == '@') { la2 = LA(2); if (SQOperator_set0.Contains(la2)) { - // line 177 + // line 178 _type = TT.Literal; value = SpecialLiteral(); } else if (la2 == '{') { - // line 198 + // line 199 _type = TT.LTokenLiteral; Skip(); Skip(); @@ -876,7 +878,7 @@ public override Maybe NextToken() break; case '`': { - // line 178 + // line 179 _type = TT.BQId; value = Id(); } @@ -895,15 +897,10 @@ public override Maybe NextToken() case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - { - // line 179 - _type = TT.Id; - value = Id(); - } - break; + goto matchId; case '\n': case '\r': { - // line 180 + // line 181 _type = TT.Newline; value = Newline(); } @@ -912,7 +909,7 @@ public override Maybe NextToken() { la1 = LA(1); if (la1 == '/') { - // line 181 + // line 182 _type = TT.SLComment; value = SLComment(); } else if (la1 == '*') { @@ -920,7 +917,7 @@ public override Maybe NextToken() if (la2 != -1) { la3 = LA(3); if (la3 != -1) { - // line 182 + // line 183 _type = TT.MLComment; value = MLComment(); } else @@ -995,7 +992,7 @@ public override Maybe NextToken() if (la2 == '\'') goto matchSQString; else { - // line 187 + // line 188 _type = TT.NormalOp; value = SQOperator(); } @@ -1004,7 +1001,7 @@ public override Maybe NextToken() if (la2 == '\'') goto matchSQString; else { - // line 197 + // line 198 _type = TT.LTokenLiteral; Skip(); Skip(); @@ -1017,75 +1014,75 @@ public override Maybe NextToken() break; case ',': { - // line 189 + // line 190 _type = TT.Comma; Skip(); - // line 189 + // line 190 value = GSymbol.Empty; } break; case ';': { - // line 190 + // line 191 _type = TT.Semicolon; Skip(); - // line 190 + // line 191 value = GSymbol.Empty; } break; case '(': { - // line 191 + // line 192 _type = TT.LParen; Skip(); - // line 191 + // line 192 _brackStack.Add(_type); } break; case ')': { - // line 192 + // line 193 _type = TT.RParen; Skip(); - // line 192 + // line 193 if (_brackStack.Count > 1) _brackStack.Pop(); } break; case '[': { - // line 193 + // line 194 _type = TT.LBrack; Skip(); - // line 193 + // line 194 _brackStack.Add(_type); } break; case ']': { - // line 194 + // line 195 _type = TT.RBrack; Skip(); - // line 194 + // line 195 if (_brackStack.Count > 1) _brackStack.Pop(); } break; case '{': { - // line 195 + // line 196 _type = TT.LBrace; Skip(); - // line 195 + // line 196 _brackStack.Add(_type); } break; case '}': { - // line 196 + // line 197 _type = TT.RBrace; Skip(); - // line 196 + // line 197 if (_brackStack.Count > 1) _brackStack.Pop(); } @@ -1100,37 +1097,44 @@ public override Maybe NextToken() goto error; } break; + matchId: + { + // line 180 + _type = TT.Id; + value = Id(); + } + break; matchNumber: { - // line 183 + // line 184 _type = TT.Literal; value = Number(); } break; matchTQString: { - // line 184 + // line 185 _type = TT.Literal; value = TQString(); } break; matchDQString: { - // line 185 + // line 186 _type = TT.Literal; value = DQString(); } break; matchSQString: { - // line 186 + // line 187 _type = TT.Literal; value = SQString(); } break; match13: { - // line 188 + // line 189 _type = TT.Unknown; Skip(); Skip(); @@ -1138,21 +1142,21 @@ public override Maybe NextToken() break; match24: { - // line 199 + // line 200 _type = TT.At; Skip(); - // line 199 + // line 200 value = GSymbol.Empty; } break; error: { Skip(); - // line 201 + // line 202 _type = TT.Unknown; } } while (false); - // line 203 + // line 204 Debug.Assert(InputPosition > _startPosition); return new Token((int) _type, _startPosition, InputPosition - _startPosition, _style, value); } @@ -1160,7 +1164,7 @@ public override Maybe NextToken() new public bool TDQStringLine() { int la0, la1, la2; - // Line 213: nongreedy([^\$])* + // Line 214: nongreedy([^\$])* for (;;) { switch (LA0) { case '\n': case '\r': @@ -1188,17 +1192,17 @@ public override Maybe NextToken() } } stop:; - // Line 213: (Newline | ["] ["] ["]) + // Line 214: (Newline | ["] ["] ["]) la0 = LA0; if (la0 == '\n' || la0 == '\r') { Newline(true); - // line 213 + // line 214 return false; } else { Match('"'); Match('"'); Match('"'); - // line 213 + // line 214 return true; } } @@ -1206,7 +1210,7 @@ public override Maybe NextToken() new public bool TSQStringLine() { int la0, la1, la2; - // Line 216: nongreedy([^\$])* + // Line 217: nongreedy([^\$])* for (;;) { switch (LA0) { case '\n': case '\r': @@ -1234,17 +1238,17 @@ public override Maybe NextToken() } } stop:; - // Line 216: (Newline | ['] ['] [']) + // Line 217: (Newline | ['] ['] [']) la0 = LA0; if (la0 == '\n' || la0 == '\r') { Newline(true); - // line 216 + // line 217 return false; } else { Match('\''); Match('\''); Match('\''); - // line 216 + // line 217 return true; } } @@ -1252,7 +1256,7 @@ public override Maybe NextToken() new public bool MLCommentLine(ref int nested) { int la0, la1; - // Line 219: greedy( &{nested > 0} [*] [/] / [/] [*] / [^\$\n\r*] / [*] &!([/]) )* + // Line 220: greedy( &{nested > 0} [*] [/] / [/] [*] / [^\$\n\r*] / [*] &!([/]) )* for (;;) { la0 = LA0; if (la0 == '*') { @@ -1261,7 +1265,7 @@ public override Maybe NextToken() if (la1 == '/') { Skip(); Skip(); - // line 219 + // line 220 nested--; } else if (la1 != -1) goto match4; @@ -1286,7 +1290,7 @@ public override Maybe NextToken() if (la1 == '*') { Skip(); Skip(); - // line 220 + // line 221 nested++; } else Skip(); @@ -1301,16 +1305,16 @@ public override Maybe NextToken() Check(!Try_MLCommentLine_Test0(0), "!([/])"); } } - // Line 224: (Newline | [*] [/]) + // Line 225: (Newline | [*] [/]) la0 = LA0; if (la0 == '\n' || la0 == '\r') { Newline(true); - // line 224 + // line 225 return false; } else { Match('*'); Match('/'); - // line 224 + // line 225 return true; } } diff --git a/Core/Loyc.Syntax/LES/Les3Parser.out.cs b/Core/Loyc.Syntax/LES/Les3Parser.out.cs index 42f910ded..362f43f31 100644 --- a/Core/Loyc.Syntax/LES/Les3Parser.out.cs +++ b/Core/Loyc.Syntax/LES/Les3Parser.out.cs @@ -567,8 +567,8 @@ LNode Expr(Precedence context) } case TT.Colon: { - if ((TT) LA(0 + 1) != TT.Newline) { - if (CanParse(context, 0, out prec)) + if (CanParse(context, 0, out prec)) { + if ((TT) LA(0 + 1) != TT.Newline) goto matchExpr; else goto stop; diff --git a/Core/Loyc.Syntax/LES/Les3PrettyPrinter.cs b/Core/Loyc.Syntax/LES/Les3PrettyPrinter.cs index bc8e575e3..ecfd47151 100644 --- a/Core/Loyc.Syntax/LES/Les3PrettyPrinter.cs +++ b/Core/Loyc.Syntax/LES/Les3PrettyPrinter.cs @@ -13,7 +13,7 @@ namespace Loyc.Syntax.Les /// control codes. /// /// - /// Call to create an instance, then call + /// Create an instance by invoking the constructor, then call /// for console output, /// for HTML output, or /// for just control codes. @@ -21,7 +21,7 @@ namespace Loyc.Syntax.Les public sealed class Les3PrettyPrinter : Les3Printer { /// The lookup table of strings for control codes ( - /// values) to HTML classes, used by . + /// values) to HTML classes, used by . /// This property is null by default, which causes the default /// table to be used. See for more /// information. @@ -180,14 +180,10 @@ public static string[] GetDefaultCssClassTable() internal static readonly string[] DefaultCssClassTable = GetDefaultCssClassTable(); /// Prints an LNode as LESv3 with HTML syntax highlighting elements. - /// A syntax tree to print. + /// Syntax trees to print. /// Output StringBuilder for HTML code. - /// A sink for warning messages, if any. /// Whether to wrap the output in "<pre class='highlight'><code>" tags. - /// How to indent inner lines of the output (usually a tab or spaces). - /// What to write to output for each newline. - /// CSS class table for span tags, - /// see . + /// Options to control the style for code printing. /// The output StringBuilder public static StringBuilder PrintToHtml( IEnumerable nodes, StringBuilder output = null, @@ -198,7 +194,7 @@ public static StringBuilder PrintToHtml( return pp.PrintToHtml(nodes, output, addPreCode); } - /// + /// public StringBuilder PrintToHtml(IEnumerable nodes, StringBuilder output = null, bool addPreCode = true) { var newline = Options.NewlineString; @@ -208,7 +204,7 @@ public StringBuilder PrintToHtml(IEnumerable nodes, StringBuilder output return PrintToHtmlCore(SB, output, addPreCode, newline, ColorCodesToCssClasses); } - /// + /// public StringBuilder PrintToHtml(ILNode node, StringBuilder output = null, bool addPreCode = true) { var newline = Options.NewlineString; diff --git a/Core/Loyc.Syntax/LNodes/ILNode.cs b/Core/Loyc.Syntax/LNodes/ILNode.cs index ec23a46d2..00ebabed3 100644 --- a/Core/Loyc.Syntax/LNodes/ILNode.cs +++ b/Core/Loyc.Syntax/LNodes/ILNode.cs @@ -36,7 +36,7 @@ namespace Loyc.Syntax /// corresponding to the attributes and arguments. /// /// Tip: the LES node printer can print any ILNode as a string. See - /// + /// /// public interface ILNode : IToLNode, IEquatable, IHasValue, INegListSource, IHasLocation { diff --git a/Core/Loyc.Syntax/LNodes/ILNodePrinter.cs b/Core/Loyc.Syntax/LNodes/ILNodePrinter.cs index 87a9291ad..abb7e9ffc 100644 --- a/Core/Loyc.Syntax/LNodes/ILNodePrinter.cs +++ b/Core/Loyc.Syntax/LNodes/ILNodePrinter.cs @@ -24,7 +24,7 @@ public interface ILNodePrinter void Print(LNode node, StringBuilder target, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null); /// Serializes a list of syntax trees to a StringBuilder in the syntax supported by this object. - /// Syntax trees to print. + /// Syntax trees to print. /// An output buffer, to which output is appended. /// An object used to print warning and error messages. If /// this is null, messages are sent to . diff --git a/Core/Loyc.Syntax/LNodes/ILNodePrintingOptions.cs b/Core/Loyc.Syntax/LNodes/ILNodePrintingOptions.cs index a9a4fa974..3f364bab9 100644 --- a/Core/Loyc.Syntax/LNodes/ILNodePrintingOptions.cs +++ b/Core/Loyc.Syntax/LNodes/ILNodePrintingOptions.cs @@ -32,8 +32,7 @@ public interface ILNodePrinterOptions /// spaces to be printed as attributes in order to ensure faithful round-trip /// parsing. /// Note: Some printers may ignore , - /// and when this - /// flag is true. + /// and when this flag is true. bool PrintTriviaExplicitly { get; } /// If there are multiple ways to print a given node, this option diff --git a/Core/Loyc.Syntax/LNodes/LNode.cs b/Core/Loyc.Syntax/LNodes/LNode.cs index d8cebc947..16f41cf15 100644 --- a/Core/Loyc.Syntax/LNodes/LNode.cs +++ b/Core/Loyc.Syntax/LNodes/LNode.cs @@ -137,7 +137,7 @@ public enum LNodeKind { Id, Literal, Call } /// the Target is not a symbol, the call has no name.) /// /// An expression in parenthesis is now represented by a call with the - /// #trivia_inParens attribute; use to + /// #trivia_inParens attribute; use to /// detect the parentheses. /// /// The problems that motivated a redesign are described at @@ -727,7 +727,7 @@ public static ILNodePrinter Printer /// /// public static PushedPrinter PushPrinter(ILNodePrinter printer) { return new PushedPrinter(printer); } - /// Returned by . + /// Returned by . public struct PushedPrinter : IDisposable { ILNodePrinter old; @@ -780,7 +780,7 @@ public override string ToString() } /// Compares two lists of nodes for structural equality. - /// Whether to compare values of + /// Whether to pay attention to and trivia attributes /// Position information is not compared. public static bool Equals(VList a, VList b, CompareMode mode = CompareMode.Normal) { @@ -792,7 +792,7 @@ public static bool Equals(VList a, VList b, CompareMode mode = Com return true; } - /// + /// public static bool Equals(ILNode a, ILNode b, CompareMode mode = CompareMode.Normal) { if ((object)a == b) @@ -850,7 +850,7 @@ public enum CompareMode { Normal = 0, Styles = 1, IgnoreTrivia = 2 } /// Compares two nodes for structural equality. Two nodes are /// considered equal if they have the same kind, the same name, the same /// value, the same arguments, and the same attributes. - /// Whether to compare values of + /// Whether to pay attention to and trivia attributes /// Position information () is not compared. public virtual bool Equals(ILNode other, CompareMode mode) { return Equals(this, other, mode); } public bool Equals(LNode other) { return Equals(this, other); } @@ -1119,7 +1119,7 @@ public enum ReplaceOpt /// ) using the specified selector. This method can also /// be used for simple searching, by giving a selector that always returns /// null. - /// The selector is called for each descendant, and + /// This method is called for each descendant, and /// optionally the root node. If the selector returns a node, the new node /// replaces the node that was passed to selector and the children of /// the new node are ignored. If the selector returns null, children of the diff --git a/Core/Loyc.Syntax/LeMP/IMacroContext.cs b/Core/Loyc.Syntax/LeMP/IMacroContext.cs index 55e46ae11..e4107118d 100644 --- a/Core/Loyc.Syntax/LeMP/IMacroContext.cs +++ b/Core/Loyc.Syntax/LeMP/IMacroContext.cs @@ -217,9 +217,6 @@ public static IEnumerable> GetOptions(VList o } /// Data returned from - /// If this type is provided an empty list of macro names, the name - /// of the method associated with the macro delegate is used as a name, so that - /// the list will never be empty. public class MacroInfo : LexicalMacroAttribute { public MacroInfo(Symbol @namespace, string name, LexicalMacro macro) : this(@namespace, new LexicalMacroAttribute("", "", name), macro) { } diff --git a/Core/Loyc.Syntax/PrinterState.cs b/Core/Loyc.Syntax/PrinterState.cs index 290e669e1..a8541b896 100644 --- a/Core/Loyc.Syntax/PrinterState.cs +++ b/Core/Loyc.Syntax/PrinterState.cs @@ -117,7 +117,7 @@ public Checkpoint GetCheckpoint() { } /// Writes a newline and the appropriate amount of indentation afterward. - /// Whether to call Indent() beore writing the newline + /// Amount by which to change before writing the newline /// A that can be used to revoke the newline /// Note that "revoking" a newline does NOT restore the original indent level. public Checkpoint Newline(int changeIndentLevel = 0) diff --git a/Core/Loyc.Essentials/Utilities/GoInterface test project/GoInterface tests.csproj b/Core/Loyc.Utilities/GoInterface test project/GoInterface tests.csproj similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterface test project/GoInterface tests.csproj rename to Core/Loyc.Utilities/GoInterface test project/GoInterface tests.csproj diff --git a/Core/Loyc.Essentials/Utilities/GoInterface test project/GoInterface tests.sln b/Core/Loyc.Utilities/GoInterface test project/GoInterface tests.sln similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterface test project/GoInterface tests.sln rename to Core/Loyc.Utilities/GoInterface test project/GoInterface tests.sln diff --git a/Core/Loyc.Essentials/Utilities/GoInterface test project/Program.cs b/Core/Loyc.Utilities/GoInterface test project/Program.cs similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterface test project/Program.cs rename to Core/Loyc.Utilities/GoInterface test project/Program.cs diff --git a/Core/Loyc.Essentials/Utilities/GoInterface test project/app.config b/Core/Loyc.Utilities/GoInterface test project/app.config similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterface test project/app.config rename to Core/Loyc.Utilities/GoInterface test project/app.config diff --git a/Core/Loyc.Essentials/Utilities/GoInterface test project/nunit.framework.dll b/Core/Loyc.Utilities/GoInterface test project/nunit.framework.dll similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterface test project/nunit.framework.dll rename to Core/Loyc.Utilities/GoInterface test project/nunit.framework.dll diff --git a/Core/Loyc.Essentials/Utilities/GoInterfaceBenchmark.cs b/Core/Loyc.Utilities/GoInterfaceBenchmark.cs similarity index 100% rename from Core/Loyc.Essentials/Utilities/GoInterfaceBenchmark.cs rename to Core/Loyc.Utilities/GoInterfaceBenchmark.cs diff --git a/Main/LeMP.StdMacros/ReplaceMacro.cs b/Main/LeMP.StdMacros/ReplaceMacro.cs index 5936159b2..ed3b76e62 100644 --- a/Main/LeMP.StdMacros/ReplaceMacro.cs +++ b/Main/LeMP.StdMacros/ReplaceMacro.cs @@ -178,7 +178,7 @@ public static LNode replaceFn(LNode node, IMacroContext context1) MacroMode mode, modes = 0; var leftoverAttrs = node.Attrs.SmartWhere(attr => { - if (attr.IsId && Enum.TryParse(attr.Name.Name, out mode)) + if (attr.IsId && Loyc.Compatibility.EnumStatic.TryParse(attr.Name.Name, out mode)) { modes |= mode; return false; diff --git a/Visual Studio Integration/LoycExtensionForVs/BraceMatchingTagger.cs b/Visual Studio Integration/LoycExtensionForVs/BraceMatchingTagger.cs index 59fe73145..c231bf0d3 100644 --- a/Visual Studio Integration/LoycExtensionForVs/BraceMatchingTagger.cs +++ b/Visual Studio Integration/LoycExtensionForVs/BraceMatchingTagger.cs @@ -17,7 +17,8 @@ namespace VS.Common // Compared to ITaggerProvider, IViewTaggerProvider is associated with a 'view' // as well as a text buffer. Needed for brace matching to know the caret position. [Export(typeof(IViewTaggerProvider))] - [ContentType("LES")] // any ContentType that wants brace matching + [ContentType("LES2")] // any ContentType that wants brace matching + [ContentType("LES3")] // any ContentType that wants brace matching [ContentType("EC#")] // any ContentType that wants brace matching [TagType(typeof(TextMarkerTag))] public sealed class DefaultBraceMatchingTaggerProvider : IViewTaggerProvider diff --git a/Visual Studio Integration/LoycExtensionForVs/EcsSyntaxForVS.cs b/Visual Studio Integration/LoycExtensionForVs/EcsSyntaxForVS.cs index 27623d399..daa951c15 100644 --- a/Visual Studio Integration/LoycExtensionForVs/EcsSyntaxForVS.cs +++ b/Visual Studio Integration/LoycExtensionForVs/EcsSyntaxForVS.cs @@ -61,7 +61,7 @@ protected override ILexer PrepareLexer(ILexer lexer, ICharSource f protected override bool IsSpecialIdentifier(object value) { - return (value is Symbol) && ((Symbol)value).Name.StartsWith("#"); + return (value is Symbol) && Loyc.Syntax.LNode.IsSpecialName((Symbol)value); } protected static IClassificationType _preprocessorType; diff --git a/Visual Studio Integration/LoycExtensionForVs/LesSyntaxForVS.cs b/Visual Studio Integration/LoycExtensionForVs/Les2SyntaxForVs.cs similarity index 88% rename from Visual Studio Integration/LoycExtensionForVs/LesSyntaxForVS.cs rename to Visual Studio Integration/LoycExtensionForVs/Les2SyntaxForVs.cs index d6c920a2a..2d2914051 100644 --- a/Visual Studio Integration/LoycExtensionForVs/LesSyntaxForVS.cs +++ b/Visual Studio Integration/LoycExtensionForVs/Les2SyntaxForVs.cs @@ -19,38 +19,34 @@ namespace Loyc.VisualStudio { - /// Boilerplate factory class for that - /// associates it with content type "LES", and associates file extensions such - /// as .les with content type "LES". + /// Boilerplate factory class for that + /// associates it with content type "LES2", and associates file extensions such + /// as .les with content type "LES2". [Export(typeof(IClassifierProvider))] [Export(typeof(ITaggerProvider))] [TagType(typeof(ClassificationTag))] [TagType(typeof(ErrorTag))] - [ContentType("LES")] - internal class LesSyntaxForVSProvider : ITaggerProvider, IClassifierProvider + [ContentType("LES2")] + internal class Les2SyntaxForVSProvider : ITaggerProvider, IClassifierProvider { [Export] - [Name("LES")] // Must match the [ContentType] attributes + [Name("LES2")] // Must match the [ContentType] attributes [BaseDefinition("code")] internal static ContentTypeDefinition _ = null; [Export] [FileExtension(".les")] - [ContentType("LES")] + [ContentType("LES2")] internal static FileExtensionToContentTypeDefinition _1 = null; [Export] - [FileExtension(".lemp")] - [ContentType("LES")] + [FileExtension(".les2")] + [ContentType("LES2")] internal static FileExtensionToContentTypeDefinition _2 = null; - [Export] - [FileExtension(".lel")] - [ContentType("LES")] - internal static FileExtensionToContentTypeDefinition _3 = null; [Import] VSImports _vs = null; - public static LesSyntaxForVS Get(VSImports vs, ITextBuffer buffer) + public static Les2SyntaxForVS Get(VSImports vs, ITextBuffer buffer) { - return buffer.Properties.GetOrCreateSingletonProperty(() => new LesSyntaxForVS(new VSBuffer(vs, buffer))); + return buffer.Properties.GetOrCreateSingletonProperty(() => new Les2SyntaxForVS(new VSBuffer(vs, buffer))); } public IClassifier GetClassifier(ITextBuffer buffer) { @@ -62,9 +58,9 @@ public ITagger CreateTagger(ITextBuffer buffer) where T : ITag } } - internal class LesSyntaxForVS : SyntaxAnalyzerForVS>> + internal class Les2SyntaxForVS : SyntaxAnalyzerForVS>> { - public LesSyntaxForVS(VSBuffer ctx) : base(ctx) + public Les2SyntaxForVS(VSBuffer ctx) : base(ctx) { var registry = ctx.VS.ClassificationRegistry; _preSufOpType = registry.GetClassificationType("LesPreSufOp"); @@ -129,15 +125,15 @@ public LesSyntaxForVS(VSBuffer ctx) : base(ctx) protected override ILexer PrepareLexer(ILexer lexer, ICharSource file, int position) { if (lexer == null) - return new LesLexer(file, "?", _lexerMessageSink, position); - ((LesLexer)lexer).Reset(file, "?", position); + return new Les2Lexer(file, "?", _lexerMessageSink, position); + ((Les2Lexer)lexer).Reset(file, "?", position); return lexer; } protected override bool IsSpecialIdentifier(object value) { return CommonKeywords.Contains(value) || - (value is Symbol) && ((Symbol)value).Name.StartsWith("#"); + (value is Symbol) && LNode.IsSpecialName((Symbol)value); } #endregion @@ -153,7 +149,7 @@ ClassificationTag MakeTag(string name) static ClassificationTag _keywordTag; static ClassificationTag _callTargetTag; - class MyLesParser : LesParser + class MyLesParser : Les2Parser { private TextSnapshotAsSourceFile _file; private IAdd> _results; diff --git a/Visual Studio Integration/LoycExtensionForVs/Les3SyntaxForVS.cs b/Visual Studio Integration/LoycExtensionForVs/Les3SyntaxForVS.cs new file mode 100644 index 000000000..9503b22f9 --- /dev/null +++ b/Visual Studio Integration/LoycExtensionForVs/Les3SyntaxForVS.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Media; +using Loyc.Collections; +using Loyc.Syntax; +using Loyc.Syntax.Les; +using Loyc.Syntax.Lexing; +using Microsoft.VisualStudio.Language.StandardClassification; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using S = Loyc.Syntax.CodeSymbols; + +namespace Loyc.VisualStudio +{ + /// Boilerplate factory class for that + /// associates it with content type "LES3", and associates file extensions such + /// as .les with content type "LES3". + [Export(typeof(IClassifierProvider))] + [Export(typeof(ITaggerProvider))] + [TagType(typeof(ClassificationTag))] + [TagType(typeof(ErrorTag))] + [ContentType("LES3")] + internal class Les3SyntaxForVSProvider : ITaggerProvider, IClassifierProvider + { + [Export] + [Name("LES3")] // Must match the [ContentType] attributes + [BaseDefinition("code")] + internal static ContentTypeDefinition _ = null; + [Export] + [FileExtension(".les3")] + [ContentType("LES3")] + internal static FileExtensionToContentTypeDefinition _1 = null; + [Export] + [FileExtension(".was")] + [ContentType("LES3")] + internal static FileExtensionToContentTypeDefinition _2 = null; + [Export] + [FileExtension(".lemp")] + [ContentType("LES3")] + internal static FileExtensionToContentTypeDefinition _3 = null; + + [Import] VSImports _vs = null; + + public static Les3SyntaxForVS Get(VSImports vs, ITextBuffer buffer) + { + return buffer.Properties.GetOrCreateSingletonProperty(() => new Les3SyntaxForVS(new VSBuffer(vs, buffer))); + } + public IClassifier GetClassifier(ITextBuffer buffer) + { + return Get(_vs, buffer); + } + public ITagger CreateTagger(ITextBuffer buffer) where T : ITag + { + return Get(_vs, buffer) as ITagger; + } + } + + internal class Les3SyntaxForVS : SyntaxAnalyzerForVS>> + { + public Les3SyntaxForVS(VSBuffer ctx) : base(ctx) + { + var registry = ctx.VS.ClassificationRegistry; + _preSufOpType = registry.GetClassificationType("LesPreSufOp"); + _keywordTag = MakeTag(PredefinedClassificationTypeNames.Keyword); + _callTargetTag = MakeTag("LoycCallTarget"); + } + + #region SyntaxClassifierForVS overrides (lexical analysis) + + static IClassificationType _preSufOpType; + + // A list of words to be highlighted in dark blue + HashSet CommonKeywords = new HashSet(new[] { + // C# keywords + "abstract", "event", "new", "struct", + "as", "explicit", "null", "switch", + "base", "extern", "object", "this", + "bool", "false", "operator", "throw", + "break", "finally", "out", "true", + "byte", "fixed", "override", "try", + "case", "float", "params", "typeof", + "catch", "for", "private", "uint", + "char", "foreach", "protected", "ulong", + "checked", "goto", "public", "unchecked", + "class", "if", "readonly", "unsafe", + "const", "implicit", "ref", "ushort", + "continue", "in", "return", "using", + "decimal", "int", "sbyte", "virtual", + "default", "interface", "sealed", "volatile", + "delegate", "internal", "short", "void", + "do", "is", "sizeof", "while", + "double", "lock", "stackalloc", + "else", "long", "static", + "enum", "namespace", "string", + // C#/LES contextual keywords (add/remove excluded because they are + // rarely used and, after all, are not real keywords. LINQ keywords + // are not likely to be used in LES so they're excluded too.) + "partial", "var", "global", "get", "set", "alias", + "select", "from", "where", "orderby", "let", + // C keywords not listed above + "auto", "unsigned", "register", "typedef", "union", + // C++ keywords not listed above + "asm", "typename", "template", "typeid", "friend", + "const_cast", "dynamic_cast", "static_cast", "reinterpret_cast", + "inline", "nullptr", "constexpr", "delete", + "mutable", "wchar_t", + // alternate operator names in C++11 + "and", "bitand", "compl", "not_eq", "or_eq", "xor_eq", "and_eq", + "bitor", "not", "or", "xor", + // Java keywords not in C# + "boolean", "extends", "final", "implements", "import", "instanceof", + "native", "package", "strictfp", "super", "synchronized", "throws", + "transient", + // python keywords not in C# + "and", "assert", "def", "del", "elif", "except", "exec", + "global", "from", "import", "lambda", "not", "or", "pass", + "raise", "with", + // other + "let" + }.Select(GSymbol.Get)); + + protected override ILexer PrepareLexer(ILexer lexer, ICharSource file, int position) + { + if (lexer == null) + return new Les3Lexer(file, "?", _lexerMessageSink, position); + ((Les3Lexer)lexer).Reset(file, "?", position); + return lexer; + } + + protected override bool IsSpecialIdentifier(object value) + { + return CommonKeywords.Contains(value) || + (value is Symbol) && LNode.IsSpecialName((Symbol)value); + } + + #endregion + + #region SyntaxAnalyzerForVS overrides (parsing on a background thread) + + ClassificationTag MakeTag(string name) + { + var type = _ctx.VS.ClassificationRegistry.GetClassificationType(name); + return new ClassificationTag(type); + } + + static ClassificationTag _keywordTag; + static ClassificationTag _callTargetTag; + + class MyLesParser : Les3Parser + { + private TextSnapshotAsSourceFile _file; + private IAdd> _results; + public MyLesParser(IList tokens, TextSnapshotAsSourceFile file, + IMessageSink messageSink, IAdd> results) + : base(tokens, file, messageSink) + { + _file = file; + _results = results; + } + + protected override LNode MarkSpecial(LNode expr) + { + var range = expr.Target.Range; + AddTag(range.StartIndex, range.Length, _keywordTag); + return base.MarkSpecial(expr); + } + protected override LNode MarkCall(LNode call) + { + var target = call.Target; + if (target.IsCall && target.BaseStyle == NodeStyle.Operator) { + if (target.CallsMin(S.Of, 1)) + target = target.Args[0]; + if (target.CallsMin(S.Dot, 1)) + target = target.Args.Last; + } + if (!target.IsCall) + AddTag(target.Range.StartIndex, target.Range.Length, _callTargetTag); + return base.MarkCall(call); + } + + void AddTag(int startIndex, int length, ClassificationTag tag) + { + var sspan = new SnapshotSpan(_file.TextSnapshot, new Span(startIndex, length)); + _results.Add(new TagSpan(sspan, tag)); + } + } + + public override IListSource> RunAnalysis(ITextSnapshot snapshot, + SparseAList eTokens, CancellationToken cancellationToken) + { + var sourceFile = new TextSnapshotAsSourceFile(snapshot); + var tokens = ToNormalTokens(eTokens); + var results = new DList>(); + var parser = new MyLesParser(tokens, sourceFile, MessageSink.Trace, results); + var _ = parser.StmtList(); + results.Sort((t1, t2) => t1.Span.Start.Position.CompareTo(t2.Span.Start.Position)); + return results; + } + + #endregion + } + + + // Classification types & color definitions defined in the source file for LES2 +} diff --git a/Visual Studio Integration/LoycExtensionForVs/LoycSyntaxForVS2010.csproj b/Visual Studio Integration/LoycExtensionForVs/LoycSyntaxForVS2010.csproj index c01163388..ea3ab1266 100644 --- a/Visual Studio Integration/LoycExtensionForVs/LoycSyntaxForVS2010.csproj +++ b/Visual Studio Integration/LoycExtensionForVs/LoycSyntaxForVS2010.csproj @@ -83,8 +83,9 @@ - + +