-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
Develop
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using Silverfly.Repl; | ||
using Silverfly.Sample.JSON; | ||
|
||
namespace Sample.JSON; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Spectre.Console; | ||
using Spectre.Console.Cli; | ||
|
||
namespace Silverfly.TreeVisualizer; | ||
|
||
public class Program | ||
{ | ||
public static int Main(string[] args) | ||
{ | ||
var app = new CommandApp<TreeCommand>(); | ||
return app.Run(args); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<PackAsTool>true</PackAsTool> | ||
<ToolCommandName>silver-tree</ToolCommandName> | ||
|
||
<Version>1.0.70</Version> | ||
<LangVersion>preview</LangVersion> | ||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||
<Title>Silverfly.TreeVisualizer</Title> | ||
<Copyright>furesoft</Copyright> | ||
<RepositoryUrl>https://github.com/furesoft/Silverfly</RepositoryUrl> | ||
<Description>A tool to view Silverfly trees</Description> | ||
<PackageTags>parser, pratt, silverfly, ast</PackageTags> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Spectre.Console" Version="0.49.1" /> | ||
<PackageReference Include="Spectre.Console.Cli" Version="0.49.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Silverfly\Silverfly.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using System.Collections; | ||
using System.ComponentModel; | ||
using System.Reflection; | ||
using Silverfly.Nodes; | ||
using Spectre.Console; | ||
using Spectre.Console.Cli; | ||
|
||
namespace Silverfly.TreeVisualizer; | ||
|
||
internal sealed class TreeCommand : Command<TreeCommand.Settings> | ||
{ | ||
public sealed class Settings : CommandSettings | ||
{ | ||
[Description("Path to the assembly containing the parsers")] | ||
[CommandArgument(0, "<assembly>")] | ||
public string? AssemblyPath { get; set; } | ||
|
||
[CommandOption("-p|--parser")] | ||
[Description("Specify the parser to use")] | ||
public string? Parser { get; set; } | ||
|
||
[Description("The source to parse")] | ||
[CommandOption("-s|--source")] | ||
public string Source { get; set; } | ||
Check warning on line 24 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
Check warning on line 24 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
|
||
} | ||
|
||
public override int Execute(CommandContext context, Settings settings) | ||
{ | ||
var parserAssembly = Assembly.LoadFrom(Path.Combine(Environment.CurrentDirectory, settings.AssemblyPath)); | ||
Check warning on line 29 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
|
||
var parserType = parserAssembly.GetType(settings.Parser); | ||
Check warning on line 30 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
|
||
var parserInstance = (Parser)Activator.CreateInstance(parserType); | ||
Check warning on line 31 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
Check warning on line 31 in Source/Silverfly.TreeVisualizer/TreeCommand.cs GitHub Actions / build-and-publish
|
||
|
||
var parsed = parserInstance.Parse(settings.Source); | ||
|
||
parserInstance.PrintMessages(); | ||
|
||
var root = new Tree(parsed.Tree.GetType().Name); | ||
|
||
BuildTree(root, parsed.Tree); | ||
|
||
AnsiConsole.Write(root); | ||
|
||
return 0; | ||
} | ||
|
||
private string[] ignorePropNames = ["Tag", "Range", "Parent"]; | ||
|
||
private void BuildTree(IHasTreeNodes node, AstNode parsedTree) | ||
{ | ||
if (parsedTree is BlockNode block) | ||
{ | ||
foreach (var child in block.Children) | ||
{ | ||
BuildTreeChild(node, child); | ||
} | ||
} | ||
else | ||
{ | ||
BuildTreeChild(node, parsedTree); | ||
} | ||
} | ||
|
||
private void BuildTreeChild(IHasTreeNodes node, object child) | ||
{ | ||
var childType = child.GetType(); | ||
var childNode = node.AddNode(childType.Name); | ||
|
||
foreach (var property in childType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) | ||
{ | ||
if (ignorePropNames.Contains(property.Name)) | ||
{ | ||
continue; | ||
} | ||
|
||
var propValue = property.GetValue(child); | ||
|
||
if (propValue is LiteralNode literal) | ||
{ | ||
childNode.AddNode($"{property.Name}={literal.Value}"); | ||
continue; | ||
} | ||
if (propValue is NameNode nameNode) | ||
{ | ||
childNode.AddNode($"{property.Name}={nameNode.Token}"); | ||
continue; | ||
} | ||
|
||
if (propValue is Token token) | ||
{ | ||
childNode.AddNode($"{property.Name}={token}"); | ||
continue; | ||
} | ||
else if (propValue is IEnumerable enumerable) | ||
{ | ||
var itemNode = childNode.AddNode($"{property.Name}"); | ||
foreach (var item in enumerable) | ||
{ | ||
BuildTreeChild(itemNode, item); | ||
} | ||
} | ||
|
||
if (propValue is AstNode childBlock) | ||
{ | ||
BuildTreeChild(childNode, childBlock); | ||
} | ||
} | ||
} | ||
} |