4141using System . Linq ;
4242using System . Windows . Forms ;
4343
44+ using Antlr4 . Runtime ;
45+ using Antlr4 . Runtime . Tree ;
46+
47+ using FastColoredTextBoxNS ;
48+
49+ using Microsoft . Msagl . Drawing ;
50+ using Microsoft . Msagl . GraphViewerGdi ;
51+ using Microsoft . Msagl . Layout . Layered ;
52+
4453using Org . Edgerunner . ANTLR4 . Tools . Testing . Grammar ;
4554
4655namespace Org . Edgerunner . ANTLR4 . Tools . Testing . GrunWin
@@ -56,6 +65,8 @@ public partial class VisualAnalyzer : Form
5665
5766 private List < string > _ParserRules ;
5867
68+ private GViewer _Viewer ;
69+
5970 private string _DefaultRule ;
6071
6172 #region Constructors And Finalizers
@@ -116,10 +127,58 @@ public bool ParseWithTracing
116127
117128 private void LoadParserRules ( )
118129 {
119- cmbRules . DataSource = _ParserRules ;
130+ cmbRules . DataSource = _ParserRules . OrderBy ( x => x ) . Distinct ( ) . ToList ( ) ;
120131 cmbRules . Refresh ( ) ;
121132 }
122133
134+ private void InitializeGraphCanvas ( )
135+ {
136+ SuspendLayout ( ) ;
137+ _Viewer = new GViewer ( ) ;
138+ pnlGraph . Controls . Add ( _Viewer ) ;
139+ _Viewer . Dock = DockStyle . Fill ;
140+ ResumeLayout ( ) ;
141+ _Viewer . LayoutAlgorithmSettingsButtonVisible = false ;
142+ _Viewer . Click += _Viewer_Click ;
143+ }
144+
145+ private void ShowSourcePosition ( ParserRuleContext context )
146+ {
147+ if ( context == null )
148+ return ;
149+
150+ var startingPlace = new Place ( context . Start . Column , context . start . Line - 1 ) ;
151+ var stoppingPlace = new Place ( context . Stop . Column + context . stop . Text . Length , context . stop . Line - 1 ) ;
152+
153+ CodeEditor . Selection = new Range ( CodeEditor , startingPlace , stoppingPlace ) ;
154+ CodeEditor . DoCaretVisible ( ) ;
155+ CodeEditor . Focus ( ) ;
156+ }
157+
158+ private void ShowSourcePosition ( TerminalNodeImpl node )
159+ {
160+ if ( node == null )
161+ return ;
162+
163+ var startingPlace = new Place ( node . Symbol . Column , node . Symbol . Line - 1 ) ;
164+ var stoppingPlace = new Place ( node . Symbol . Column + node . Symbol . Text . Length , node . Symbol . Line - 1 ) ;
165+
166+ CodeEditor . Selection = new Range ( CodeEditor , startingPlace , stoppingPlace ) ;
167+ CodeEditor . DoCaretVisible ( ) ;
168+ CodeEditor . Focus ( ) ;
169+ }
170+
171+ private void _Viewer_Click ( object sender , EventArgs e )
172+ {
173+ if ( _Viewer . SelectedObject is Node node )
174+ {
175+ if ( node . UserData is ParserRuleContext context )
176+ ShowSourcePosition ( context ) ;
177+ else if ( node . UserData is TerminalNodeImpl terminal )
178+ ShowSourcePosition ( terminal ) ;
179+ }
180+ }
181+
123182 /// <summary>
124183 /// Parses the source code.
125184 /// </summary>
@@ -131,7 +190,7 @@ public void ParseSource()
131190 if ( _ParserRules . Count == 0 )
132191 return ;
133192
134- if ( string . IsNullOrEmpty ( cmbRules . SelectedItem . ToString ( ) ) )
193+ if ( string . IsNullOrEmpty ( cmbRules . SelectedItem ? . ToString ( ) ) )
135194 return ;
136195
137196 var analyzer = new Grammar . Analyzer ( _Grammar , CodeEditor . Text ) ;
@@ -141,13 +200,31 @@ public void ParseSource()
141200 if ( ParseWithTracing ) options |= ParseOption . Trace ;
142201 analyzer . Parse ( cmbRules . SelectedItem . ToString ( ) , options ) ;
143202 PopulateTokens ( analyzer . DisplayTokens ) ;
203+ BuildParseTreeGraph ( analyzer . ParseContext ) ;
144204 }
145205
146206 private void PopulateTokens ( IList < TokenViewModel > tokens )
147207 {
148208 tokenListView . SetObjects ( tokens ) ;
149209 }
150210
211+ private void BuildParseTreeGraph ( ITree tree )
212+ {
213+ if ( _Viewer == null )
214+ return ;
215+
216+ if ( tree == null )
217+ return ;
218+
219+ var grapher = new Graphing . ParseTreeGrapher ( tree , _ParserRules )
220+ {
221+ BackgroundColor = Color . LightBlue , BorderColor = Color . Black , TextColor = Color . Black
222+ } ;
223+ var graph = grapher . CreateGraph ( ) ;
224+ graph . LayoutAlgorithmSettings = new SugiyamaLayoutSettings ( ) ;
225+ _Viewer . Graph = graph ;
226+ }
227+
151228 /// <summary>
152229 /// Sets the source code to be analyzed.
153230 /// </summary>
@@ -166,7 +243,6 @@ public void SetGrammar(GrammarReference grammar)
166243 var scanner = new Scanner ( ) ;
167244 _Grammar = grammar ;
168245 _ParserRules = scanner . GetParserRulesForGrammar ( grammar ) . ToList ( ) ;
169- _ParserRules . Sort ( ) ;
170246 LoadParserRules ( ) ;
171247 }
172248
@@ -231,5 +307,19 @@ private void loadGrammarToolStripMenuItem_Click(object sender, EventArgs e)
231307
232308 SetGrammar ( grammarToLoad ) ;
233309 }
310+
311+ private void VisualAnalyzer_Load ( object sender , EventArgs e )
312+ {
313+ InitializeGraphCanvas ( ) ;
314+
315+ if ( ! string . IsNullOrEmpty ( CodeEditor . Text ) )
316+ ParseSource ( ) ;
317+ }
318+
319+ private void cmbRules_SelectedIndexChanged ( object sender , EventArgs e )
320+ {
321+ if ( cmbRules . Items . Count > 0 )
322+ ParseSource ( ) ;
323+ }
234324 }
235325}
0 commit comments