-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
1,458 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup> | ||
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' < '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> | ||
<HasSharedItems>true</HasSharedItems> | ||
<SharedGUID>cc83f717-2d1d-4b45-bead-be7fa88bb71c</SharedGUID> | ||
</PropertyGroup> | ||
<PropertyGroup Label="Configuration"> | ||
<Import_RootNamespace>Debuggee</Import_RootNamespace> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="$(MSBuildThisFileDirectory)VisualizerDataObjectSource.cs" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup Label="Globals"> | ||
<ProjectGuid>cc83f717-2d1d-4b45-bead-be7fa88bb71c</ProjectGuid> | ||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> | ||
</PropertyGroup> | ||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" /> | ||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" /> | ||
<PropertyGroup /> | ||
<Import Project="Debuggee.projitems" Label="Shared" /> | ||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" /> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Reflection; | ||
using ParseTreeVisualizer.Serialization; | ||
using Periscope.Debuggee; | ||
|
||
namespace ParseTreeVisualizer { | ||
public class VisualizerDataObjectSource : VisualizerObjectSourceBase<object, Config> { | ||
public override object GetResponse(object target, Config config) => new VisualizerData(target, config); | ||
public override string GetConfigKey(object target) => Assembly.GetAssembly(target.GetType()).GetName().Name; | ||
} | ||
} |
Submodule Periscope.Debuggee
updated
from 000000 to fc461a
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net452</TargetFramework> | ||
<RootNamespace>ParseTreeVisualizer.Runtime.Debuggee</RootNamespace> | ||
<AssemblyName>ParseTreeVisualizer.Runtime.Debuggee</AssemblyName> | ||
<LangVersion>9.0</LangVersion> | ||
<Nullable>enable</Nullable> | ||
<DefineConstants>VISUALIZER_DEBUGGEE, ANTLR_RUNTIME</DefineConstants> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | ||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath> | ||
<OutputPath>bin/$(Configuration)/net2.0/</OutputPath> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> | ||
<PackageReference Include="ZSpitz.Util" Version="0.1.112" /> | ||
<Reference Include="Microsoft.VisualStudio.DebuggerVisualizers"> | ||
<HintPath>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.DebuggerVisualizers.dll</HintPath> | ||
<Private>false</Private> | ||
</Reference> | ||
<PackageReference Include="Antlr4.Runtime" Version="4.6.6" /> | ||
</ItemGroup> | ||
|
||
<Import Project="..\Serialization\Serialization.projitems" Label="Serialization" /> | ||
<Import Project="..\Debuggee\Debuggee.projitems" Label="Debuggee" /> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
using System; | ||
|
||
namespace RuntimeStandard.Debuggee { | ||
public class Class1 { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using Antlr4.Runtime; | ||
using Antlr4.Runtime.Tree; | ||
using System; | ||
using System.CodeDom.Compiler; | ||
using System.Collections.ObjectModel; | ||
using System.Linq; | ||
using System.Reflection; | ||
using ZSpitz.Util; | ||
|
||
namespace ParseTreeVisualizer.Serialization { | ||
[Serializable] | ||
public class ClassInfo { | ||
public static readonly ClassInfo None = new("(None)"); | ||
|
||
public string Name { get; } | ||
public string? Namespace { get; } | ||
public string? Assembly { get; } | ||
public string? Antlr { get; private set; } // Runtime - in Antlr.Runtime, <number> - version | ||
public string? FullName { get; } | ||
public string? RuleName { get; } | ||
public int? RuleID { get; } | ||
|
||
public ReadOnlyCollection<string>? MethodNames { get; } | ||
|
||
private ClassInfo(string name) => Name = name; | ||
public ClassInfo(Type t, string? ruleName = null, int? ruleID = null, bool loadMethodNames = false) { | ||
if (t is null) { throw new ArgumentNullException(nameof(t)); } | ||
|
||
Name = t.Name; | ||
Namespace = t.Namespace; | ||
Assembly = t.Assembly.Location; | ||
if (t.Assembly == typeof(IParseTree).Assembly) { | ||
Antlr = "Runtime"; | ||
} else if (t.GetCustomAttribute<GeneratedCodeAttribute>() is var attr) { | ||
Antlr = attr.Version; | ||
} | ||
FullName = t.FullName; | ||
RuleName = ruleName.IsNullOrWhitespace() ? null : ruleName; | ||
RuleID = ruleID; | ||
|
||
if (loadMethodNames) { | ||
MethodNames = t.GetMethods() | ||
.Where(x => !x.IsSpecialName && x.ReturnType.InheritsFromOrImplements<ParserRuleContext>()) | ||
.Select(x => x.Name) | ||
.Where(x => x != "GetInvokingContext") | ||
.Ordered() | ||
.ToList() | ||
.AsReadOnly(); | ||
} | ||
} | ||
|
||
public override string ToString() => FullName ?? Name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using Periscope.Debuggee; | ||
using System; | ||
using System.Collections.Generic; | ||
using ZSpitz.Util; | ||
|
||
namespace ParseTreeVisualizer.Serialization { | ||
[Serializable] | ||
#if VISUALIZER_DEBUGGEE | ||
public class Config : Periscope.Debuggee.ConfigBase<Config> { | ||
#else | ||
public class Config { | ||
#endif | ||
|
||
public string? SelectedParserName { get; set; } | ||
public string? ParseTokensWithRule { get; set; } | ||
public string? SelectedLexerName { get; set; } | ||
public bool ShowTextTokens { get; set; } = true; | ||
public bool ShowWhitespaceTokens { get; set; } = true; | ||
public bool ShowErrorTokens { get; set; } = true; | ||
public HashSet<int> SelectedTokenTypes { get; } = new HashSet<int>(); | ||
public bool ShowTreeTextTokens { get; set; } = true; | ||
public bool ShowTreeWhitespaceTokens { get; set; } = true; | ||
public bool ShowTreeErrorTokens { get; set; } = true; | ||
public bool ShowRuleContextNodes { get; set; } = true; | ||
public HashSet<string?> SelectedRuleContexts { get; } = new HashSet<string?>(); | ||
public string? RootNodePath { get; set; } | ||
|
||
public bool HasTreeFilter() => !(ShowTreeErrorTokens && ShowTreeWhitespaceTokens && ShowTreeTextTokens && ShowRuleContextNodes && SelectedRuleContexts.None()); | ||
public bool HasTokenListFilter() => !(ShowTextTokens && ShowErrorTokens && ShowWhitespaceTokens && SelectedTokenTypes.None()); | ||
|
||
#if VISUALIZER_DEBUGGEE | ||
// TODO should any parts of the config return ConfigDiffStates.NeedsWrite? | ||
public override ConfigDiffStates Diff(Config baseline) => | ||
( | ||
baseline.SelectedParserName == SelectedParserName && | ||
baseline.SelectedLexerName == SelectedLexerName && | ||
baseline.ShowTextTokens == ShowTextTokens && | ||
baseline.ShowErrorTokens == ShowErrorTokens && | ||
baseline.ShowWhitespaceTokens == ShowWhitespaceTokens && | ||
baseline.ShowTreeTextTokens == ShowTreeTextTokens && | ||
baseline.ShowTreeErrorTokens == ShowTreeErrorTokens && | ||
baseline.ShowTreeWhitespaceTokens == ShowTreeWhitespaceTokens && | ||
baseline.ShowRuleContextNodes == ShowRuleContextNodes && | ||
baseline.ParseTokensWithRule == ParseTokensWithRule && | ||
baseline.SelectedTokenTypes.SetEquals(SelectedTokenTypes) && | ||
baseline.SelectedRuleContexts.SetEquals(SelectedRuleContexts) | ||
) ? ConfigDiffStates.NoAction : ConfigDiffStates.NeedsTransfer; | ||
|
||
public override Config Clone() { | ||
#else | ||
public Config Clone() { | ||
#endif | ||
var ret = new Config { | ||
SelectedParserName = SelectedParserName, | ||
SelectedLexerName = SelectedLexerName, | ||
ShowTextTokens = ShowTextTokens, | ||
ShowErrorTokens = ShowErrorTokens, | ||
ShowWhitespaceTokens = ShowWhitespaceTokens, | ||
ShowTreeTextTokens = ShowTreeTextTokens, | ||
ShowTreeErrorTokens = ShowTreeErrorTokens, | ||
ShowTreeWhitespaceTokens = ShowTreeWhitespaceTokens, | ||
ShowRuleContextNodes = ShowRuleContextNodes, | ||
ParseTokensWithRule = ParseTokensWithRule | ||
}; | ||
SelectedTokenTypes.AddRangeTo(ret.SelectedTokenTypes); | ||
SelectedRuleContexts.AddRangeTo(ret.SelectedRuleContexts); | ||
return ret; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
namespace ParseTreeVisualizer.Serialization { | ||
public enum TreeNodeType { | ||
RuleContext, | ||
Token, | ||
ErrorToken, | ||
WhitespaceToken, | ||
Placeholder | ||
} | ||
|
||
public enum FilterStates { | ||
NotMatched, | ||
Matched, | ||
DescendantMatched | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using Antlr4.Runtime.Tree; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace ParseTreeVisualizer { | ||
public static class Extensions { | ||
public static IEnumerable<IParseTree> Children(this IParseTree tree) { | ||
for (var i = 0; i < tree.ChildCount; i++) { | ||
yield return tree.GetChild(i); | ||
} | ||
} | ||
|
||
public static IEnumerable<IParseTree> Descendants(this IParseTree tree) { | ||
for (var i = 0; i < tree.ChildCount; i++) { | ||
var child = tree.GetChild(i); | ||
yield return child; | ||
foreach (var descendant in child.Descendants()) { | ||
yield return descendant; | ||
} | ||
} | ||
} | ||
|
||
public static string GetPositionedText(this IParseTree tree, char filler = ' ') { | ||
var sb = new StringBuilder(); | ||
foreach (var descendant in tree.Descendants().OfType<TerminalNodeImpl>()) { | ||
var fillerCharCount = descendant.Payload.StartIndex - sb.Length; | ||
if (fillerCharCount > 0) { | ||
sb.Append(filler, fillerCharCount); | ||
} | ||
sb.Append(descendant.Payload.Text); | ||
} | ||
return sb.ToString(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
using Antlr4.Runtime; | ||
using Antlr4.Runtime.Tree; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using ZSpitz.Util; | ||
|
||
namespace ParseTreeVisualizer.Serialization { | ||
[Serializable] | ||
public class ParseTreeNode { | ||
public static ParseTreeNode GetPlaceholder(ParseTreeNode? actualRoot) => | ||
actualRoot is null ? | ||
throw new ArgumentNullException(nameof(actualRoot)) : | ||
new("(parent nodes)", TreeNodeType.Placeholder, new List<ParseTreeNode> { actualRoot }, actualRoot.CharSpan); | ||
|
||
public string? Caption { get; private set; } | ||
public List<PropertyValue>? Properties { get; } | ||
public List<ParseTreeNode> Children { get; private set; } | ||
public (int startTokenIndex, int endTokenIndex) TokenSpan { get; } | ||
public (int startChar, int endChar) CharSpan { get; private set; } | ||
public TreeNodeType? NodeType { get; private set; } | ||
public FilterStates? FilterState { get; } | ||
public string? Path { get; } | ||
|
||
private ParseTreeNode(string caption, TreeNodeType nodeType, List<ParseTreeNode> children, (int startChar, int endChar) charSpan) { | ||
Caption = caption; | ||
NodeType = nodeType; | ||
Children = children; | ||
CharSpan = charSpan; | ||
} | ||
public ParseTreeNode(IParseTree tree, List<Token> tokens, string[] ruleNames, Dictionary<int, string> tokenTypeMapping, Config config, Dictionary<Type, (string? caption, int? index)> ruleMapping, string? path) { | ||
if (tree is null) { throw new ArgumentNullException(nameof(tree)); } | ||
if (ruleMapping is null) { throw new ArgumentNullException(nameof(ruleMapping)); } | ||
if (tokens is null) { throw new ArgumentNullException(nameof(tokens)); } | ||
if (config is null) { throw new ArgumentNullException(nameof(config)); } | ||
|
||
var type = tree.GetType(); | ||
|
||
if (tree is ParserRuleContext ruleContext) { | ||
NodeType = TreeNodeType.RuleContext; | ||
|
||
var caption = type.Name; | ||
if (!ruleMapping.TryGetValue(type, out var x)) { | ||
var ruleIndex = (int)(type.GetProperty("RuleIndex")?.GetValue(tree) ?? -1); | ||
if (ruleNames.TryGetValue(ruleIndex, out caption)) { | ||
ruleMapping[type] = (caption, ruleIndex); | ||
} else { | ||
caption = type.Name; | ||
ruleMapping[type] = (null, null); | ||
} | ||
} else { | ||
caption = x.caption; | ||
} | ||
|
||
Caption = caption; | ||
CharSpan = (ruleContext.Start.StartIndex, ruleContext.Stop?.StopIndex ?? int.MaxValue); | ||
} else if (tree is TerminalNodeImpl terminalNode) { | ||
var token = new Token(terminalNode, tokenTypeMapping); | ||
|
||
if (token.IsError) { | ||
Caption = token.Text; | ||
NodeType = TreeNodeType.ErrorToken; | ||
} else { | ||
Caption = $"\"{token.Text}\""; | ||
NodeType = token.IsWhitespace ? TreeNodeType.WhitespaceToken : TreeNodeType.Token; | ||
} | ||
CharSpan = token.Span; | ||
|
||
if (token.ShowToken(config)) { | ||
tokens.Add(token); | ||
} | ||
} | ||
|
||
Path = path; | ||
var pathDelimiter = path.IsNullOrWhitespace() ? "" : "."; | ||
Properties = type.GetProperties().OrderBy(x => x.Name).Select(prp => new PropertyValue(tree, prp)).ToList(); | ||
Children = tree.Children() | ||
.Select((x, index) => new ParseTreeNode(x, tokens, ruleNames, tokenTypeMapping, config, ruleMapping, $"{path}{pathDelimiter}{index}")) | ||
.Where(x => x.FilterState != FilterStates.NotMatched) // intentionally doesn't exclude null | ||
.ToList(); | ||
TokenSpan = (tree.SourceInterval.a, tree.SourceInterval.b); | ||
|
||
var matched = true; | ||
if (config.HasTreeFilter()) { | ||
matched = NodeType switch { | ||
TreeNodeType.RuleContext => | ||
config.ShowRuleContextNodes && ( | ||
config.SelectedRuleContexts.None() || | ||
type.FullName.In(config.SelectedRuleContexts) | ||
), | ||
TreeNodeType.ErrorToken => config.ShowErrorTokens, | ||
TreeNodeType.WhitespaceToken => config.ShowTreeWhitespaceTokens, | ||
_ => config.ShowTreeTextTokens | ||
}; | ||
|
||
FilterState = | ||
matched ? | ||
FilterStates.Matched : | ||
(Children.Any(x => x.FilterState.In(FilterStates.Matched, FilterStates.DescendantMatched)) ? | ||
FilterStates.DescendantMatched : | ||
FilterStates.NotMatched); | ||
} | ||
|
||
var toPromote = Children | ||
.Select((child, index) => (grandchild: child.Children.SingleOrDefaultExt(x => x.FilterState.In(FilterStates.Matched, FilterStates.DescendantMatched)), index)) | ||
.WhereT((grandchild, index) => grandchild != null) | ||
.ToList(); | ||
foreach (var (grandchild, index) in toPromote) { | ||
Children[index] = grandchild; | ||
} | ||
} | ||
|
||
public string Stringify(int indentLevel = 0) { | ||
var ret = new string(' ', indentLevel * 4) + Caption; | ||
foreach (var child in Children) { | ||
ret += "\n" + child.Stringify(indentLevel + 1); | ||
} | ||
return ret; | ||
} | ||
} | ||
} |
Oops, something went wrong.