/Examples/SciChart.Examples.Demo/CodeHighlighter/Parsing/LanguageParser.cs

https://github.com/ABTSoftware/SciChart.WPF.Examples · C# · 204 lines · 164 code · 34 blank · 6 comment · 23 complexity · d349bfaf56466a21d4adb62956ff80cf MD5 · raw file

  1. // (c) Copyright Microsoft Corporation.
  2. // This source is subject to the Microsoft Public License (Ms-PL).
  3. // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  4. // All other rights reserved.
  5. // <auto-generated />
  6. // No style analysis for imported project.
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text.RegularExpressions;
  10. using CodeHighlighter.Common;
  11. using CodeHighlighter.Compilation;
  12. namespace CodeHighlighter.Parsing
  13. {
  14. internal class LanguageParser : ILanguageParser
  15. {
  16. private readonly ILanguageCompiler languageCompiler;
  17. private readonly ILanguageRepository languageRepository;
  18. public LanguageParser(ILanguageCompiler languageCompiler,
  19. ILanguageRepository languageRepository)
  20. {
  21. this.languageCompiler = languageCompiler;
  22. this.languageRepository = languageRepository;
  23. }
  24. public void Parse(string sourceCode,
  25. ILanguage language,
  26. Action<string, IList<Scope>> parseHandler)
  27. {
  28. if (string.IsNullOrEmpty(sourceCode))
  29. return;
  30. CompiledLanguage compiledLanguage = languageCompiler.Compile(language);
  31. Parse(sourceCode, compiledLanguage, parseHandler);
  32. }
  33. private void Parse(string sourceCode,
  34. CompiledLanguage compiledLanguage,
  35. Action<string, IList<Scope>> parseHandler)
  36. {
  37. Match regexMatch = compiledLanguage.Regex.Match(sourceCode);
  38. if (!regexMatch.Success)
  39. parseHandler(sourceCode, new List<Scope>());
  40. else
  41. {
  42. int currentIndex = 0;
  43. while (regexMatch.Success)
  44. {
  45. string sourceCodeBeforeMatch = sourceCode.Substring(currentIndex, regexMatch.Index - currentIndex);
  46. if (!string.IsNullOrEmpty(sourceCodeBeforeMatch))
  47. parseHandler(sourceCodeBeforeMatch, new List<Scope>());
  48. string matchedSourceCode = sourceCode.Substring(regexMatch.Index, regexMatch.Length);
  49. if (!string.IsNullOrEmpty(matchedSourceCode))
  50. {
  51. List<Scope> capturedStylesForMatchedFragment = GetCapturedStyles(regexMatch, regexMatch.Index, compiledLanguage);
  52. List<Scope> capturedStyleTree = CreateCapturedStyleTree(capturedStylesForMatchedFragment);
  53. parseHandler(matchedSourceCode, capturedStyleTree);
  54. }
  55. currentIndex = regexMatch.Index + regexMatch.Length;
  56. regexMatch = regexMatch.NextMatch();
  57. }
  58. string sourceCodeAfterAllMatches = sourceCode.Substring(currentIndex);
  59. if (!string.IsNullOrEmpty(sourceCodeAfterAllMatches))
  60. parseHandler(sourceCodeAfterAllMatches, new List<Scope>());
  61. }
  62. }
  63. private static List<Scope> CreateCapturedStyleTree(IList<Scope> capturedStyles)
  64. {
  65. capturedStyles.SortStable((x, y) => x.Index.CompareTo(y.Index));
  66. var capturedStyleTree = new List<Scope>(capturedStyles.Count);
  67. Scope currentScope = null;
  68. foreach (Scope capturedStyle in capturedStyles)
  69. {
  70. if (currentScope == null)
  71. {
  72. capturedStyleTree.Add(capturedStyle);
  73. currentScope = capturedStyle;
  74. continue;
  75. }
  76. AddScopeToNestedScopes(capturedStyle, ref currentScope, capturedStyleTree);
  77. }
  78. return capturedStyleTree;
  79. }
  80. private static void AddScopeToNestedScopes(Scope scope,
  81. ref Scope currentScope,
  82. ICollection<Scope> capturedStyleTree)
  83. {
  84. if (scope.Index >= currentScope.Index && (scope.Index + scope.Length <= currentScope.Index + currentScope.Length))
  85. {
  86. currentScope.AddChild(scope);
  87. currentScope = scope;
  88. }
  89. else
  90. {
  91. currentScope = currentScope.Parent;
  92. if (currentScope != null)
  93. AddScopeToNestedScopes(scope, ref currentScope, capturedStyleTree);
  94. else
  95. capturedStyleTree.Add(scope);
  96. }
  97. }
  98. private List<Scope> GetCapturedStyles(Match regexMatch,
  99. int currentIndex,
  100. CompiledLanguage compiledLanguage)
  101. {
  102. var capturedStyles = new List<Scope>();
  103. for (int i = 0; i < regexMatch.Groups.Count; i++)
  104. {
  105. Group regexGroup = regexMatch.Groups[i];
  106. string styleName = compiledLanguage.Captures[i];
  107. if (regexGroup.Length == 0 || String.IsNullOrEmpty(styleName))
  108. continue;
  109. else
  110. foreach (Capture regexCapture in regexGroup.Captures)
  111. AppendCapturedStylesForRegexCapture(regexCapture, currentIndex, styleName, capturedStyles);
  112. }
  113. return capturedStyles;
  114. }
  115. private void AppendCapturedStylesForRegexCapture(Capture regexCapture,
  116. int currentIndex,
  117. string styleName,
  118. ICollection<Scope> capturedStyles)
  119. {
  120. if (styleName.StartsWith(ScopeName.LanguagePrefix))
  121. {
  122. string nestedGrammarId = styleName.Substring(1);
  123. AppendCapturedStylesForNestedLanguage(regexCapture, regexCapture.Index - currentIndex, nestedGrammarId, capturedStyles);
  124. }
  125. else
  126. capturedStyles.Add(new Scope(styleName, regexCapture.Index - currentIndex, regexCapture.Length));
  127. }
  128. private void AppendCapturedStylesForNestedLanguage(Capture regexCapture,
  129. int offset,
  130. string nestedLanguageId,
  131. ICollection<Scope> capturedStyles)
  132. {
  133. ILanguage nestedLanguage = languageRepository.FindById(nestedLanguageId);
  134. if (nestedLanguage == null)
  135. throw new InvalidOperationException("The nested language was not found in the language repository.");
  136. else
  137. {
  138. CompiledLanguage nestedCompiledLanguage = languageCompiler.Compile(nestedLanguage);
  139. Match regexMatch = nestedCompiledLanguage.Regex.Match(regexCapture.Value, 0, regexCapture.Value.Length);
  140. if (!regexMatch.Success)
  141. return;
  142. else
  143. {
  144. while (regexMatch.Success)
  145. {
  146. List<Scope> capturedStylesForMatchedFragment = GetCapturedStyles(regexMatch, 0, nestedCompiledLanguage);
  147. List<Scope> capturedStyleTree = CreateCapturedStyleTree(capturedStylesForMatchedFragment);
  148. foreach (Scope nestedCapturedStyle in capturedStyleTree)
  149. {
  150. IncreaseCapturedStyleIndicies(capturedStyleTree, offset);
  151. capturedStyles.Add(nestedCapturedStyle);
  152. }
  153. regexMatch = regexMatch.NextMatch();
  154. }
  155. }
  156. }
  157. }
  158. private static void IncreaseCapturedStyleIndicies(IList<Scope> capturedStyles,
  159. int amountToIncrease)
  160. {
  161. for (int i = 0; i < capturedStyles.Count; i++)
  162. {
  163. Scope scope = capturedStyles[i];
  164. scope.Index += amountToIncrease;
  165. if (scope.Children.Count > 0)
  166. IncreaseCapturedStyleIndicies(scope.Children, amountToIncrease);
  167. }
  168. }
  169. }
  170. }