Start implementing Evaluator
This commit is contained in:
parent
f4921ac9f9
commit
8c1ddb0cf7
@ -1,5 +1,4 @@
|
||||
using Parser;
|
||||
using Semantics;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -72,7 +71,7 @@ namespace ConsoleDemo
|
||||
var childNodesAndTokens = root.GetChildNodesAndTokens();
|
||||
var node = childNodesAndTokens[0].AsNode();
|
||||
var classChildNodesAndTokens = node.GetChildNodesAndTokens();
|
||||
var c = GetClass.FromTree(root, fileName);
|
||||
var c = Semantics.GetClass.FromTree(root, fileName);
|
||||
Console.WriteLine(c.Name);
|
||||
foreach (var m in c.Methods)
|
||||
{
|
||||
@ -86,13 +85,13 @@ namespace ConsoleDemo
|
||||
|
||||
public static void ContextDemo()
|
||||
{
|
||||
var context = new Context();
|
||||
var context = new Semantics.Context();
|
||||
context.ScanPath(BaseDirectory);
|
||||
}
|
||||
|
||||
public static void DumbPrinterDemo()
|
||||
{
|
||||
var context = new Context();
|
||||
var context = new Semantics.Context();
|
||||
context.ScanPath(BaseDirectory);
|
||||
var fileName = Path.Combine(
|
||||
BaseDirectory,
|
||||
@ -105,7 +104,7 @@ namespace ConsoleDemo
|
||||
|
||||
public static void UsageDemo()
|
||||
{
|
||||
var context = new Context();
|
||||
var context = new Semantics.Context();
|
||||
context.ScanPath(BaseDirectory);
|
||||
var fileName = Path.Combine(
|
||||
BaseDirectory,
|
||||
@ -130,7 +129,6 @@ namespace ConsoleDemo
|
||||
//ContextDemo();
|
||||
//DumbPrinterDemo();
|
||||
//UsageDemo();
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
Parser/Compilation.cs
Normal file
23
Parser/Compilation.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace Parser
|
||||
{
|
||||
public class Compilation
|
||||
{
|
||||
private readonly SyntaxTree _syntaxTree;
|
||||
|
||||
private Compilation(SyntaxTree syntaxTree)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
}
|
||||
|
||||
public static Compilation Create(SyntaxTree syntaxTree)
|
||||
{
|
||||
return new Compilation(syntaxTree);
|
||||
}
|
||||
|
||||
public EvaluationResult Evaluate(CompilationContext context)
|
||||
{
|
||||
var evaluator = new Evaluator(_syntaxTree, context);
|
||||
return evaluator.Evaluate();
|
||||
}
|
||||
}
|
||||
}
|
7
Parser/CompilationContext.cs
Normal file
7
Parser/CompilationContext.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Parser
|
||||
{
|
||||
public class CompilationContext
|
||||
{
|
||||
public static CompilationContext Empty => new CompilationContext();
|
||||
}
|
||||
}
|
19
Parser/EvaluationResult.cs
Normal file
19
Parser/EvaluationResult.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Parser.Internal;
|
||||
using Parser.Objects;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public class EvaluationResult
|
||||
{
|
||||
public EvaluationResult(MObject? value, ImmutableArray<Diagnostic> diagnostics)
|
||||
{
|
||||
Value = value;
|
||||
Diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
public MObject? Value { get; }
|
||||
|
||||
public ImmutableArray<Diagnostic> Diagnostics { get; }
|
||||
}
|
||||
}
|
282
Parser/Evaluator.cs
Normal file
282
Parser/Evaluator.cs
Normal file
@ -0,0 +1,282 @@
|
||||
using Parser.Internal;
|
||||
using Parser.Objects;
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
internal class Evaluator
|
||||
{
|
||||
private SyntaxTree _syntaxTree;
|
||||
private CompilationContext _context;
|
||||
private DiagnosticsBag _diagnostics;
|
||||
|
||||
public Evaluator(SyntaxTree syntaxTree, CompilationContext context)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_context = context;
|
||||
_diagnostics = new DiagnosticsBag();
|
||||
}
|
||||
|
||||
internal EvaluationResult Evaluate()
|
||||
{
|
||||
var result = EvaluateFile(_syntaxTree.Root);
|
||||
return new EvaluationResult(result, _diagnostics.ToImmutableArray());
|
||||
}
|
||||
|
||||
private MObject? EvaluateFile(FileSyntaxNode root)
|
||||
{
|
||||
MObject? lastResult = null;
|
||||
foreach (var nodeOrToken in root.StatementList)
|
||||
{
|
||||
if (nodeOrToken.IsNode)
|
||||
{
|
||||
var statement = (StatementSyntaxNode)nodeOrToken.AsNode()!;
|
||||
lastResult = EvaluateStatement(statement) ?? lastResult;
|
||||
}
|
||||
}
|
||||
|
||||
return lastResult;
|
||||
}
|
||||
|
||||
private MObject? EvaluateStatement(StatementSyntaxNode statement)
|
||||
{
|
||||
return statement.Kind switch
|
||||
{
|
||||
TokenKind.ExpressionStatement =>
|
||||
EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement),
|
||||
TokenKind.MethodDefinition =>
|
||||
EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement),
|
||||
TokenKind.AbstractMethodDeclaration =>
|
||||
EvaluateAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)statement),
|
||||
TokenKind.FunctionDeclaration =>
|
||||
EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement),
|
||||
TokenKind.SwitchStatement =>
|
||||
EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement),
|
||||
TokenKind.WhileStatement =>
|
||||
EvaluateWhileStatement((WhileStatementSyntaxNode)statement),
|
||||
TokenKind.IfStatement =>
|
||||
EvaluateIfStatement((IfStatementSyntaxNode)statement),
|
||||
TokenKind.ForStatement =>
|
||||
EvaluateForStatement((ForStatementSyntaxNode)statement),
|
||||
TokenKind.TryCatchStatement =>
|
||||
EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement),
|
||||
TokenKind.EmptyStatement =>
|
||||
EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement),
|
||||
TokenKind.ClassDeclaration =>
|
||||
EvaluateClassDeclaration((ClassDeclarationSyntaxNode)statement),
|
||||
_ => throw new NotImplementedException($"Invalid statement kind '{statement.Kind}'."),
|
||||
};
|
||||
}
|
||||
|
||||
private MObject? EvaluateClassDeclaration(ClassDeclarationSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateEmptyStatement(EmptyStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateTryCatchStatement(TryCatchStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateForStatement(ForStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateIfStatement(IfStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateWhileStatement(WhileStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateSwitchStatement(SwitchStatementSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateFunctionDeclaration(FunctionDeclarationSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateAbstractMethodDeclaration(AbstractMethodDeclarationSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateMethodDefinition(MethodDefinitionSyntaxNode statement)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateExpressionStatement(ExpressionStatementSyntaxNode statement)
|
||||
{
|
||||
return EvaluateExpression(statement.Expression);
|
||||
}
|
||||
|
||||
private MObject? EvaluateExpression(ExpressionSyntaxNode expression)
|
||||
{
|
||||
return expression.Kind switch
|
||||
{
|
||||
TokenKind.Lambda =>
|
||||
EvaluateLambda((LambdaSyntaxNode)expression),
|
||||
TokenKind.AssignmentExpression =>
|
||||
EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression),
|
||||
TokenKind.EmptyExpression =>
|
||||
EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression),
|
||||
TokenKind.UnaryPrefixOperationExpression =>
|
||||
EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression),
|
||||
TokenKind.CompoundName =>
|
||||
EvaluateCompoundName((CompoundNameSyntaxNode)expression),
|
||||
TokenKind.BinaryOperation =>
|
||||
EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression),
|
||||
TokenKind.IdentifierName =>
|
||||
EvaluateIdentifierName((IdentifierNameSyntaxNode)expression),
|
||||
TokenKind.NumberLiteralExpression =>
|
||||
EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression),
|
||||
TokenKind.StringLiteralExpression =>
|
||||
EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression),
|
||||
TokenKind.DoubleQuotedStringLiteralExpression =>
|
||||
EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression),
|
||||
TokenKind.UnquotedStringLiteralExpression =>
|
||||
EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression),
|
||||
TokenKind.ArrayLiteralExpression =>
|
||||
EvaluateArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)expression),
|
||||
TokenKind.CellArrayLiteralExpression =>
|
||||
EvaluateCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)expression),
|
||||
TokenKind.ParenthesizedExpression =>
|
||||
EvaluateNamedFunctionHandle((NamedFunctionHandleSyntaxNode)expression),
|
||||
TokenKind.CellArrayElementAccess =>
|
||||
EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression),
|
||||
TokenKind.FunctionCall =>
|
||||
EvaluateFunctionCall((FunctionCallExpressionSyntaxNode)expression),
|
||||
TokenKind.MemberAccess =>
|
||||
EvaluateMemberAccess((MemberAccessSyntaxNode)expression),
|
||||
TokenKind.UnaryPostfixOperationExpression =>
|
||||
EvaluateUnaryPostfixOperationExpression((UnaryPostixOperationExpressionSyntaxNode)expression),
|
||||
TokenKind.IndirectMemberAccess =>
|
||||
EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression),
|
||||
TokenKind.Command =>
|
||||
EvaluateCommand((CommandExpressionSyntaxNode)expression),
|
||||
TokenKind.ClassInvokation =>
|
||||
EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression),
|
||||
_ => throw new NotImplementedException($"Invalid expression kind '{expression.Kind}'."),
|
||||
};
|
||||
}
|
||||
|
||||
private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateCommand(CommandExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateIndirectMemberAccess(IndirectMemberAccessSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateUnaryPostfixOperationExpression(UnaryPostixOperationExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateMemberAccess(MemberAccessSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateCellArrayLiteralExpression(CellArrayLiteralExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateArrayLiteralExpression(ArrayLiteralExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateUnquotedStringLiteralExpression(UnquotedStringLiteralSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateIdentifierName(IdentifierNameSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateBinaryOperation(BinaryOperationExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateCompoundName(CompoundNameSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateEmptyExpression(EmptyExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateAssignmentExpression(AssignmentExpressionSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateLambda(LambdaSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private MObject? EvaluateNamedFunctionHandle(NamedFunctionHandleSyntaxNode expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Parser.Internal;
|
||||
using Parser.Internal;
|
||||
using System.Linq;
|
||||
|
||||
namespace Parser
|
||||
@ -27,18 +25,4 @@ namespace Parser
|
||||
return new SyntaxTree(root, totalDiagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
public class SyntaxTree
|
||||
{
|
||||
public SyntaxTree(RootSyntaxNode nullRoot, DiagnosticsBag diagnostics)
|
||||
{
|
||||
NullRoot = nullRoot ?? throw new ArgumentNullException(nameof(nullRoot));
|
||||
Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
|
||||
}
|
||||
|
||||
public RootSyntaxNode NullRoot { get; }
|
||||
public FileSyntaxNode Root => NullRoot.File;
|
||||
public DiagnosticsBag Diagnostics { get; }
|
||||
}
|
||||
|
||||
}
|
6
Parser/Objects/MDoubleNumber.cs
Normal file
6
Parser/Objects/MDoubleNumber.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Parser.Objects
|
||||
{
|
||||
public class MDoubleNumber : MObject
|
||||
{
|
||||
}
|
||||
}
|
6
Parser/Objects/MObject.cs
Normal file
6
Parser/Objects/MObject.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Parser.Objects
|
||||
{
|
||||
public abstract class MObject
|
||||
{
|
||||
}
|
||||
}
|
27
Parser/SyntaxTree.cs
Normal file
27
Parser/SyntaxTree.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Parser.Internal;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public class SyntaxTree
|
||||
{
|
||||
public SyntaxTree(RootSyntaxNode nullRoot, DiagnosticsBag diagnostics)
|
||||
{
|
||||
NullRoot = nullRoot ?? throw new ArgumentNullException(nameof(nullRoot));
|
||||
Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
|
||||
}
|
||||
|
||||
public RootSyntaxNode NullRoot { get; }
|
||||
public FileSyntaxNode Root => NullRoot.File;
|
||||
public DiagnosticsBag Diagnostics { get; }
|
||||
|
||||
public static SyntaxTree Parse(string text)
|
||||
{
|
||||
var window = new TextWindowWithNull(text);
|
||||
var parser = new MParser(window);
|
||||
var tree = parser.Parse();
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,63 +5,74 @@ namespace Repl
|
||||
{
|
||||
public class MRepl
|
||||
{
|
||||
private readonly CompilationContext _context;
|
||||
|
||||
public MRepl()
|
||||
{
|
||||
_context = CompilationContext.Empty;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Console.Write("> ");
|
||||
var line = Console.ReadLine();
|
||||
var window = new TextWindowWithNull(line);
|
||||
var parser = new MParser(window);
|
||||
var tree = parser.Parse();
|
||||
if (tree.Diagnostics.Diagnostics.Count > 0)
|
||||
var line = Read();
|
||||
if (line.StartsWith('#'))
|
||||
{
|
||||
foreach (var diagnostic in tree.Diagnostics.Diagnostics)
|
||||
line = line.Trim();
|
||||
if (line == "#q")
|
||||
{
|
||||
Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}");
|
||||
break;
|
||||
}
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine($"Unknown command '{line}'.");
|
||||
Console.ResetColor();
|
||||
continue;
|
||||
}
|
||||
var result = Evaluate(line);
|
||||
Print(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void Print(string result)
|
||||
{
|
||||
Console.Write(result);
|
||||
}
|
||||
|
||||
private string Read()
|
||||
{
|
||||
Console.Write("> ");
|
||||
return Console.ReadLine();
|
||||
}
|
||||
|
||||
private string Evaluate(string submission)
|
||||
{
|
||||
var tree = SyntaxTree.Parse(submission);
|
||||
var compilation = Compilation.Create(tree);
|
||||
if (tree.Diagnostics.Diagnostics.Count > 0)
|
||||
{
|
||||
foreach (var diagnostic in tree.Diagnostics.Diagnostics)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
TreeRenderer.RenderTree(tree);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TreeRenderer
|
||||
{
|
||||
private static void RenderToken(SyntaxToken token, string indent, bool isLast)
|
||||
{
|
||||
Console.Write(indent + (isLast ? "└── " : "├── "));
|
||||
Console.Write($"<{token.Kind}>");
|
||||
Console.Write($" {token.Text}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
TreeRenderer.RenderTree(tree);
|
||||
|
||||
private static void RenderNode(SyntaxNode node, string indent, bool isLast)
|
||||
{
|
||||
Console.Write(indent);
|
||||
Console.Write(isLast ? "└── " : "├── ");
|
||||
Console.Write($"<{node.Kind}>");
|
||||
Console.WriteLine();
|
||||
var children = node.GetChildNodesAndTokens();
|
||||
var last = children.Count - 1;
|
||||
indent += isLast ? " " : "│ ";
|
||||
for (var index = 0; index <= last; index++)
|
||||
var evaluationResult = compilation.Evaluate(_context);
|
||||
|
||||
foreach (var diagnostic in evaluationResult.Diagnostics)
|
||||
{
|
||||
var child = children[index];
|
||||
if (child.IsNode)
|
||||
{
|
||||
RenderNode(child.AsNode(), indent, index == last);
|
||||
}
|
||||
else if (child.IsToken)
|
||||
{
|
||||
RenderToken(child.AsToken(), indent, index == last);
|
||||
}
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}");
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderTree(SyntaxTree tree)
|
||||
{
|
||||
RenderNode(tree.Root, "", true);
|
||||
return evaluationResult.Value?.ToString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
44
Repl/TreeRenderer.cs
Normal file
44
Repl/TreeRenderer.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using Parser;
|
||||
|
||||
namespace Repl
|
||||
{
|
||||
public class TreeRenderer
|
||||
{
|
||||
private static void RenderToken(SyntaxToken token, string indent, bool isLast)
|
||||
{
|
||||
Console.Write(indent + (isLast ? "└── " : "├── "));
|
||||
Console.Write($"<{token.Kind}>");
|
||||
Console.Write($" {token.Text}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static void RenderNode(SyntaxNode node, string indent, bool isLast)
|
||||
{
|
||||
Console.Write(indent);
|
||||
Console.Write(isLast ? "└── " : "├── ");
|
||||
Console.Write($"<{node.Kind}>");
|
||||
Console.WriteLine();
|
||||
var children = node.GetChildNodesAndTokens();
|
||||
var last = children.Count - 1;
|
||||
indent += isLast ? " " : "│ ";
|
||||
for (var index = 0; index <= last; index++)
|
||||
{
|
||||
var child = children[index];
|
||||
if (child.IsNode)
|
||||
{
|
||||
RenderNode(child.AsNode(), indent, index == last);
|
||||
}
|
||||
else if (child.IsToken)
|
||||
{
|
||||
RenderToken(child.AsToken(), indent, index == last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderTree(SyntaxTree tree)
|
||||
{
|
||||
RenderNode(tree.Root, "", true);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user