4040using System . Collections . Generic ;
4141using System . IO ;
4242using System . Linq ;
43+ using System . Reflection ;
4344using System . Windows . Forms ;
4445
4546using Antlr4 . Runtime ;
5556using Microsoft . Msagl . GraphViewerGdi ;
5657using Microsoft . Msagl . Layout . Layered ;
5758
59+ using Org . Edgerunner . ANTLR4 . Tools . Common ;
5860using Org . Edgerunner . ANTLR4 . Tools . Graphing ;
5961using Org . Edgerunner . ANTLR4 . Tools . Testing . Grammar ;
6062using Org . Edgerunner . ANTLR4 . Tools . Testing . Grammar . Errors ;
6163using Org . Edgerunner . ANTLR4 . Tools . Testing . GrunWin . Properties ;
6264
65+ using Style = FastColoredTextBoxNS . Style ;
66+
6367namespace Org . Edgerunner . ANTLR4 . Tools . Testing . GrunWin
6468{
6569 /// <summary>
@@ -73,10 +77,20 @@ public partial class VisualAnalyzer : Form
7377
7478 private GrammarReference _Grammar ;
7579
80+ private IEditorGuide _EditorGuide ;
81+
82+ private Dictionary < string , FastColoredTextBoxNS . Style > _TokenStyles ;
83+
84+ private Style _ErrorStyle ;
85+
7686 private List < string > _ParserRules ;
7787
7888 private GViewer _Viewer ;
7989
90+ private IList < TokenViewModel > _Tokens ;
91+
92+ private List < ParseMessage > _ParseErrors ;
93+
8094 #region Constructors And Finalizers
8195
8296 /// <summary>
@@ -85,6 +99,8 @@ public partial class VisualAnalyzer : Form
8599 public VisualAnalyzer ( )
86100 {
87101 InitializeComponent ( ) ;
102+
103+ _TokenStyles = new Dictionary < string , FastColoredTextBoxNS . Style > ( ) ;
88104 }
89105
90106 #endregion
@@ -160,8 +176,10 @@ public void ParseSource()
160176 if ( ParseWithSllMode ) options |= ParseOption . Sll ;
161177 if ( ParseWithTracing ) options |= ParseOption . Trace ;
162178 analyzer . Parse ( CmbRules . SelectedItem . ToString ( ) , options , listener ) ;
179+ _Tokens = analyzer . DisplayTokens ;
163180 PopulateTokens ( analyzer . DisplayTokens ) ;
164- PopulateParserMessages ( listener . Errors ) ;
181+ _ParseErrors = listener . Errors ;
182+ PopulateParserMessages ( _ParseErrors ) ;
165183 BuildParseTreeTreeViewGuide ( analyzer . ParseContext ) ;
166184 BuildParseTreeGraph ( analyzer . ParseContext ) ;
167185 }
@@ -194,6 +212,10 @@ public void SetGrammar(GrammarReference grammar)
194212 _ParserRules = scanner . GetParserRulesForGrammar ( grammar ) . ToList ( ) ;
195213 LoadParserRules ( ) ;
196214 stripLabelGrammarName . Text = grammar . GrammarName ;
215+
216+ // Now try to load an IEditorGuide instance for the specified Grammar
217+ _TokenStyles . Clear ( ) ;
218+ LoadEditorGuide ( grammar ) ;
197219 }
198220
199221 /// <summary>
@@ -267,6 +289,45 @@ private void BuildParseTreeTreeViewGuide(ITree tree)
267289 ParseTreeView . ResumeLayout ( ) ;
268290 }
269291
292+ private void LoadEditorGuide ( [ NotNull ] GrammarReference grammar )
293+ {
294+ if ( grammar == null )
295+ throw new ArgumentNullException ( nameof ( grammar ) ) ;
296+
297+ _EditorGuide = null ;
298+ _ErrorStyle = null ;
299+
300+ var scanner = new Scanner ( ) ;
301+ var loader = new Loader ( ) ;
302+
303+ // First try loading a guide from the target assembly's directory
304+ var pathRoot = Path . GetDirectoryName ( grammar . AssemblyPath ) ;
305+ if ( LoadGuideFromPath ( grammar , scanner , loader , pathRoot ) )
306+ return ;
307+
308+ // Now try loading a guide from the Grun.Net Guides folder
309+ pathRoot = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . CodeBase ) ;
310+ pathRoot = Path . Combine ( pathRoot , "Guides" ) ;
311+ if ( Directory . Exists ( pathRoot ) )
312+ LoadGuideFromPath ( grammar , scanner , loader , pathRoot ) ;
313+ }
314+
315+ private bool LoadGuideFromPath ( GrammarReference grammar , Scanner scanner , Loader loader , string pathRoot )
316+ {
317+ var guideReferences = scanner . LocateAllEditorGuides ( pathRoot ?? throw new InvalidOperationException ( ) ) ;
318+ foreach ( var reference in guideReferences )
319+ {
320+ var guide = loader . LoadEditorGuide ( reference ) ;
321+ if ( guide != null && guide . GrammarName == grammar . GrammarName )
322+ {
323+ _EditorGuide = guide ;
324+ return true ;
325+ }
326+ }
327+
328+ return false ;
329+ }
330+
270331 private void ParserRulesCombo_SelectedIndexChanged ( object sender , EventArgs e )
271332 {
272333 if ( CmbRules . Items . Count > 0 )
@@ -276,6 +337,66 @@ private void ParserRulesCombo_SelectedIndexChanged(object sender, EventArgs e)
276337 private void CodeEditor_TextChanged ( object sender , TextChangedEventArgs e )
277338 {
278339 ParseSource ( ) ;
340+ //CodeEditor.ClearStylesBuffer();
341+ ColorizeTokens ( ) ;
342+ ColorizeErrors ( ) ;
343+ }
344+
345+ private void ColorizeErrors ( )
346+ {
347+ if ( _EditorGuide == null )
348+ return ;
349+
350+ foreach ( var error in _ParseErrors )
351+ {
352+ var token = error . Token ;
353+ var startingPlace = new Place ( token . Column , token . Line - 1 ) ;
354+ var stoppingPlace = new Place ( token . Column + token . Text . Length , token . Line - 1 ) ;
355+ var tokenRange = CodeEditor . GetRange ( startingPlace , stoppingPlace ) ;
356+ tokenRange . SetStyle ( GetParseErrorStyle ( ) ) ;
357+ }
358+ }
359+
360+ private void ColorizeTokens ( )
361+ {
362+ if ( _EditorGuide == null )
363+ return ;
364+
365+ CodeEditor . BeginUpdate ( ) ;
366+ try
367+ {
368+ foreach ( var token in _Tokens )
369+ {
370+ var startingPlace = new Place ( token . ActualToken . Column , token . ActualToken . Line - 1 ) ;
371+ var stoppingPlace = new Place ( token . ActualToken . Column + token . Text . Length , token . ActualToken . Line - 1 ) ;
372+ var tokenRange = CodeEditor . GetRange ( startingPlace , stoppingPlace ) ;
373+ tokenRange . ClearStyle ( StyleIndex . All ) ;
374+ var style = GetTokenStyle ( token ) ;
375+ tokenRange . SetStyle ( style ) ;
376+ }
377+ }
378+ finally
379+ {
380+ CodeEditor . EndUpdate ( ) ;
381+ }
382+ }
383+
384+ private Style GetTokenStyle ( TokenViewModel token )
385+ {
386+ if ( _TokenStyles . TryGetValue ( token . Type , out var style ) )
387+ return style ;
388+
389+ var foregroundBrush = _EditorGuide . GetTokenForegroundBrush ( token . Type ) ;
390+ var backgroundBrush = _EditorGuide . GetTokenBackgroundBrush ( token . Type ) ;
391+ var fontStyle = _EditorGuide . GetTokenFontStyle ( token . Type ) ;
392+ style = new TextStyle ( foregroundBrush , backgroundBrush , fontStyle ) ;
393+ _TokenStyles [ token . Type ] = style ;
394+ return style ;
395+ }
396+
397+ private Style GetParseErrorStyle ( )
398+ {
399+ return _ErrorStyle ?? ( _ErrorStyle = new WavyLineStyle ( 240 , _EditorGuide . ErrorColor ) ) ;
279400 }
280401
281402 private void ExitToolStripMenuItem_Click ( object sender , EventArgs e )
0 commit comments