Skip to content

Commit d739d87

Browse files
committed
Begun adding support for the IEditorGuide interface.
1 parent 1e77279 commit d739d87

File tree

9 files changed

+305
-5
lines changed

9 files changed

+305
-5
lines changed

GunWin/GrammarSelector.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using System.Threading.Tasks;
99
using System.Windows.Forms;
1010

11+
using Org.Edgerunner.ANTLR4.Tools.Testing.Grammar;
12+
1113
namespace Org.Edgerunner.ANTLR4.Tools.Testing.GrunWin
1214
{
1315
public partial class GrammarSelector : Form

GunWin/GunWin.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@
126126
<Project>{ec6f674c-4d48-40c4-b28b-85627c1ea3ce}</Project>
127127
<Name>Code Grapher</Name>
128128
</ProjectReference>
129+
<ProjectReference Include="..\Common\Common.csproj">
130+
<Project>{8bd992fd-a3b3-4af9-9371-5aa14ddfda68}</Project>
131+
<Name>Common</Name>
132+
</ProjectReference>
129133
<ProjectReference Include="..\TestRig\TestRig.csproj">
130134
<Project>{4e020f1d-27bf-4853-8573-474d7edb4e72}</Project>
131135
<Name>TestRig</Name>

GunWin/Options.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class Options
4949
[Option("rule", HelpText = "ANTLR grammar rule to use", Required = false)]
5050
public string RuleName { get; set; }
5151

52-
[Option("input-file", HelpText = "File name to parse", Required = false)]
52+
[Option("file", HelpText = "File name to parse", Required = false)]
5353
public string FileName { get; set; }
5454

5555
[Option("trace", HelpText = "Trace grammar parsing", Required = false)]

GunWin/VisualAnalyzer.cs

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
using System.Collections.Generic;
4141
using System.IO;
4242
using System.Linq;
43+
using System.Reflection;
4344
using System.Windows.Forms;
4445

4546
using Antlr4.Runtime;
@@ -55,11 +56,14 @@
5556
using Microsoft.Msagl.GraphViewerGdi;
5657
using Microsoft.Msagl.Layout.Layered;
5758

59+
using Org.Edgerunner.ANTLR4.Tools.Common;
5860
using Org.Edgerunner.ANTLR4.Tools.Graphing;
5961
using Org.Edgerunner.ANTLR4.Tools.Testing.Grammar;
6062
using Org.Edgerunner.ANTLR4.Tools.Testing.Grammar.Errors;
6163
using Org.Edgerunner.ANTLR4.Tools.Testing.GrunWin.Properties;
6264

65+
using Style = FastColoredTextBoxNS.Style;
66+
6367
namespace 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)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#region BSD 3-Clause License
2+
// <copyright file="EditorGuideReference.cs" company="Edgerunner.org">
3+
// Copyright 2020
4+
// </copyright>
5+
//
6+
// BSD 3-Clause License
7+
//
8+
// Copyright (c) 2020,
9+
// All rights reserved.
10+
//
11+
// Redistribution and use in source and binary forms, with or without
12+
// modification, are permitted provided that the following conditions are met:
13+
//
14+
// 1. Redistributions of source code must retain the above copyright notice, this
15+
// list of conditions and the following disclaimer.
16+
//
17+
// 2. Redistributions in binary form must reproduce the above copyright notice,
18+
// this list of conditions and the following disclaimer in the documentation
19+
// and/or other materials provided with the distribution.
20+
//
21+
// 3. Neither the name of the copyright holder nor the names of its
22+
// contributors may be used to endorse or promote products derived from
23+
// this software without specific prior written permission.
24+
//
25+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35+
#endregion
36+
37+
using System;
38+
39+
using JetBrains.Annotations;
40+
41+
namespace Org.Edgerunner.ANTLR4.Tools.Testing.Grammar
42+
{
43+
public class EditorGuideReference
44+
{
45+
/// <summary>
46+
/// Initializes a new instance of the <see cref="EditorGuideReference"/> class.
47+
/// </summary>
48+
/// <param name="guideType">Type of the guide.</param>
49+
/// <param name="assemblyPath">The assembly.</param>
50+
/// <exception cref="ArgumentNullException">
51+
/// guideType
52+
/// or
53+
/// assembly are null.
54+
/// </exception>
55+
public EditorGuideReference([NotNull] Type guideType, [NotNull] string assemblyPath)
56+
{
57+
if (string.IsNullOrEmpty(assemblyPath))
58+
throw new ArgumentNullException(nameof(assemblyPath));
59+
60+
GuideType = guideType ?? throw new ArgumentNullException(nameof(guideType));
61+
AssemblyPath = assemblyPath;
62+
}
63+
64+
public Type GuideType { get; }
65+
66+
public string AssemblyPath { get; }
67+
}
68+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
using JetBrains.Annotations;
4343

44-
namespace Org.Edgerunner.ANTLR4.Tools.Testing
44+
namespace Org.Edgerunner.ANTLR4.Tools.Testing.Grammar
4545
{
4646
/// <summary>
4747
/// Class that represents a reference to an ANTLR grammar.

TestRig/Grammar/Loader.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@
3535
#endregion
3636

3737
using System;
38+
using System.Collections.Generic;
3839
using System.IO;
3940
using System.Reflection;
4041

4142
using Antlr4.Runtime;
4243

4344
using JetBrains.Annotations;
4445

46+
using Org.Edgerunner.ANTLR4.Tools.Common;
47+
4548
namespace Org.Edgerunner.ANTLR4.Tools.Testing.Grammar
4649
{
4750
/// <summary>
@@ -90,5 +93,46 @@ public Antlr4.Runtime.Parser LoadParser([NotNull] GrammarReference reference, [N
9093
var lexer = Activator.CreateInstance(reference.Parser, stream) as Parser;
9194
return lexer;
9295
}
96+
97+
/// <summary>
98+
/// Loads an <see cref="IEditorGuide"/> instance for the referenced grammar.
99+
/// </summary>
100+
/// <param name="reference">The editor guide reference.</param>
101+
/// <returns>A new <see cref="IEditorGuide" />.</returns>
102+
/// <exception cref="ArgumentNullException"><paramref name="reference"/> is <see langword="null"/></exception>
103+
/// <exception cref="T:System.ArgumentNullException"><paramref name="reference" /> is <see langword="null" /></exception>
104+
/// <exception cref="T:System.IO.FileLoadException">A file that was found could not be loaded.</exception>
105+
/// <exception cref="T:System.IO.FileNotFoundException">The assembly path is an empty string ("") or does not exist.</exception>
106+
/// <exception cref="T:System.BadImageFormatException">The assembly path is not a valid assembly.</exception>
107+
public IEditorGuide LoadEditorGuide([NotNull] EditorGuideReference reference)
108+
{
109+
if (reference is null) throw new ArgumentNullException(nameof(reference));
110+
111+
Assembly.Load(File.ReadAllBytes(reference.AssemblyPath));
112+
var guide = Activator.CreateInstance(reference.GuideType) as IEditorGuide;
113+
return guide;
114+
}
115+
116+
/// <summary>
117+
/// Loads all editor guides.
118+
/// </summary>
119+
/// <param name="references">The references to load.</param>
120+
/// <returns>An <see cref="IEnumerable{IEditorGuide}"/> instance.</returns>
121+
/// <exception cref="ArgumentNullException">references is null.</exception>
122+
/// <exception cref="T:System.IO.FileLoadException">A file that was found could not be loaded.</exception>
123+
/// <exception cref="T:System.IO.FileNotFoundException">The assembly path is an empty string ("") or does not exist.</exception>
124+
/// <exception cref="T:System.BadImageFormatException">The assembly path is not a valid assembly.</exception>
125+
public IEnumerable<IEditorGuide> LoadAllEditorGuides([NotNull] IEnumerable<EditorGuideReference> references)
126+
{
127+
if (references == null)
128+
throw new ArgumentNullException(nameof(references));
129+
130+
var results = new List<IEditorGuide>();
131+
132+
foreach (var guideReference in references)
133+
results.Add(LoadEditorGuide(guideReference));
134+
135+
return results;
136+
}
93137
}
94138
}

0 commit comments

Comments
 (0)