From e35f5f17e7f7cb4d35826fa319c10f97e20d3954 Mon Sep 17 00:00:00 2001 From: Dylan Beattie Date: Tue, 9 Jul 2024 17:53:36 +0100 Subject: [PATCH] Overhauled AST printer and added ASCII art with box drawing! --- Starship/Rockstar.Engine/Expressions/Binary.cs | 9 +++++---- .../Rockstar.Engine/Expressions/Expression.cs | 4 ++-- .../Expressions/Look\303\274p.cs" | 4 ++-- .../Rockstar.Engine/Expressions/Pronoun.cs | 4 ++-- Starship/Rockstar.Engine/Expressions/Unary.cs | 7 ++++--- .../Rockstar.Engine/Expressions/Variable.cs | 4 ++-- Starship/Rockstar.Engine/Statements/Assign.cs | 8 ++++---- Starship/Rockstar.Engine/Statements/Block.cs | 4 ++-- .../Rockstar.Engine/Statements/Conditional.cs | 16 ++++++++-------- .../Rockstar.Engine/Statements/Decrement.cs | 6 +++--- .../Rockstar.Engine/Statements/Increment.cs | 6 +++--- Starship/Rockstar.Engine/Statements/Loop.cs | 13 +++++++------ Starship/Rockstar.Engine/Statements/Output.cs | 6 +++--- .../Rockstar.Engine/Statements/Statement.cs | 3 ++- Starship/Rockstar.Engine/Values/Number.cs | 4 ++-- .../Rockstar.Engine/Values/Str\303\257ng.cs" | 4 ++-- Starship/Rockstar.Engine/Values/Value.cs | 4 ++-- Starship/Rockstar.Engine/rockstar.peg | 1 - Starship/Rockstar.Test/ConditionalTests.cs | 18 ++++++++++++++++++ .../Rockstar.Test.v3.ncrunchproject | 5 +++++ 20 files changed, 78 insertions(+), 52 deletions(-) diff --git a/Starship/Rockstar.Engine/Expressions/Binary.cs b/Starship/Rockstar.Engine/Expressions/Binary.cs index 2cd3bdf..09edae9 100644 --- a/Starship/Rockstar.Engine/Expressions/Binary.cs +++ b/Starship/Rockstar.Engine/Expressions/Binary.cs @@ -1,4 +1,5 @@ using System.Text; +using Rockstar.Engine.Statements; using Rockstar.Engine.Values; namespace Rockstar.Engine.Expressions; @@ -31,9 +32,9 @@ public Value Resolve(Func eval) { }; } - public override void Print(StringBuilder sb, int depth) { - sb.Indent(depth).AppendLine($"{op}:".ToLowerInvariant()); - lhs.Print(sb, depth + 1); - rhs.Print(sb, depth + 1); + public override void Print(StringBuilder sb, string prefix) { + lhs.Print(sb, prefix); + sb.Append(prefix).AppendLine($"{op}:".ToLowerInvariant()); + rhs.Print(sb, prefix + Statement.INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Expressions/Expression.cs b/Starship/Rockstar.Engine/Expressions/Expression.cs index 791f254..e2fb427 100644 --- a/Starship/Rockstar.Engine/Expressions/Expression.cs +++ b/Starship/Rockstar.Engine/Expressions/Expression.cs @@ -4,8 +4,8 @@ namespace Rockstar.Engine.Expressions; public abstract class Expression(Source source) { - public virtual void Print(StringBuilder sb, int depth) - => sb.Indent(depth).AppendLine(this.GetType().Name.ToLowerInvariant()); + public virtual void Print(StringBuilder sb, string prefix) + => sb.Append(prefix).AppendLine(this.GetType().Name.ToLowerInvariant()); protected string Location => source.Location; } \ No newline at end of file diff --git "a/Starship/Rockstar.Engine/Expressions/Look\303\274p.cs" "b/Starship/Rockstar.Engine/Expressions/Look\303\274p.cs" index 37d3cc4..0e12852 100644 --- "a/Starship/Rockstar.Engine/Expressions/Look\303\274p.cs" +++ "b/Starship/Rockstar.Engine/Expressions/Look\303\274p.cs" @@ -6,6 +6,6 @@ public class Looküp(Variable variable, Source source) : Expression(source) { public Variable Variable => variable; - public override void Print(StringBuilder sb, int depth) - => sb.Indent(depth).AppendLine($"lookup: {variable.Name} ({variable.GetType().Name})"); + public override void Print(StringBuilder sb, string prefix) + => sb.Append(prefix).AppendLine($"lookup: {variable.Name} ({variable.GetType().Name})"); } diff --git a/Starship/Rockstar.Engine/Expressions/Pronoun.cs b/Starship/Rockstar.Engine/Expressions/Pronoun.cs index 9d7e55b..209951c 100644 --- a/Starship/Rockstar.Engine/Expressions/Pronoun.cs +++ b/Starship/Rockstar.Engine/Expressions/Pronoun.cs @@ -6,7 +6,7 @@ public class Pronoun(string name, Source source) : Variable(name, source) { public Pronoun() : this(String.Empty) { } public Pronoun(string name) : this(name, Source.None) { } public override string Key => Name.ToLowerInvariant(); - public override void Print(StringBuilder sb, int depth) { - sb.Indent(depth).AppendLine($"pronoun: {Name}"); + public override void Print(StringBuilder sb, string prefix) { + sb.Append(prefix).AppendLine($"pronoun: {Name}"); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Expressions/Unary.cs b/Starship/Rockstar.Engine/Expressions/Unary.cs index edcd311..5d892f4 100644 --- a/Starship/Rockstar.Engine/Expressions/Unary.cs +++ b/Starship/Rockstar.Engine/Expressions/Unary.cs @@ -1,3 +1,4 @@ +using Rockstar.Engine.Statements; using System.Text; namespace Rockstar.Engine.Expressions; @@ -6,8 +7,8 @@ public class Unary(Operator op, Expression expr, Source source) : Expression(source) { public Operator Op => op; public Expression Expr => expr; - public override void Print(StringBuilder sb, int depth) { - sb.Indent(depth).AppendLine("unary: {op}"); - expr.Print(sb, depth+1); + public override void Print(StringBuilder sb, string prefix) { + sb.Append(prefix).AppendLine("unary: {op}"); + expr.Print(sb, prefix + Statement.INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Expressions/Variable.cs b/Starship/Rockstar.Engine/Expressions/Variable.cs index 74e030a..f44e1be 100644 --- a/Starship/Rockstar.Engine/Expressions/Variable.cs +++ b/Starship/Rockstar.Engine/Expressions/Variable.cs @@ -6,8 +6,8 @@ namespace Rockstar.Engine.Expressions; public abstract class Variable(string name, Source source) : Expression(source) { public string Name => name; - public override void Print(StringBuilder sb, int depth) { - sb.Indent(depth).AppendLine($"variable: {name}"); + public override void Print(StringBuilder sb, string prefix) { + sb.Append(prefix).AppendLine($"variable: {name}"); } private static readonly Regex whitespace = new("\\s+", RegexOptions.Compiled); diff --git a/Starship/Rockstar.Engine/Statements/Assign.cs b/Starship/Rockstar.Engine/Statements/Assign.cs index 52b6350..534b47d 100644 --- a/Starship/Rockstar.Engine/Statements/Assign.cs +++ b/Starship/Rockstar.Engine/Statements/Assign.cs @@ -7,9 +7,9 @@ public class Assign(Variable variable, Expression expr, Source source) : Statement(source) { public Variable Variable => variable; public Expression Expr => expr; - public override void Print(StringBuilder sb, int depth) { - sb.Indent(depth).AppendLine($"assign:"); - variable.Print(sb, depth + 1); - expr.Print(sb, depth + 1); + public override void Print(StringBuilder sb, string prefix) { + sb.Append(prefix).AppendLine($"assign:"); + variable.Print(sb, prefix + INDENT); + expr.Print(sb, prefix + INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Statements/Block.cs b/Starship/Rockstar.Engine/Statements/Block.cs index c1939c4..9f1c228 100644 --- a/Starship/Rockstar.Engine/Statements/Block.cs +++ b/Starship/Rockstar.Engine/Statements/Block.cs @@ -29,7 +29,7 @@ public override string ToString() { return sb.ToString(); } - public void Print(StringBuilder sb, int depth = 0) { - foreach (var stmt in Statements) stmt.Print(sb, depth); + public void Print(StringBuilder sb, string prefix = "") { + foreach (var stmt in Statements) stmt.Print(sb, prefix); } } diff --git a/Starship/Rockstar.Engine/Statements/Conditional.cs b/Starship/Rockstar.Engine/Statements/Conditional.cs index aff08a2..628f311 100644 --- a/Starship/Rockstar.Engine/Statements/Conditional.cs +++ b/Starship/Rockstar.Engine/Statements/Conditional.cs @@ -13,14 +13,14 @@ public Conditional Else(Block alternate) { this.Alternate = alternate; return this; } - public override void Print(StringBuilder sb, int depth = 0) { - sb.Indent(depth).AppendLine("if:"); - sb.Indent(depth + 1).AppendLine("test:"); - condition.Print(sb, depth + 2); - sb.Indent(depth + 1).AppendLine("then:"); - consequent.Print(sb, depth + 2); + public override void Print(StringBuilder sb, string prefix = "") { + sb.Append(prefix).AppendLine("if:"); + sb.Append(prefix + INDENT).AppendLine("test:"); + condition.Print(sb, prefix + INDENT + INDENT); + sb.Append(prefix + INDENT).AppendLine("then:"); + consequent.Print(sb, prefix + INDENT + INDENT); if (Alternate.IsEmpty) return; - sb.Indent(depth + 1).AppendLine("else:"); - Alternate.Print(sb, depth + 2); + sb.Append(prefix + INDENT).AppendLine("else:"); + Alternate.Print(sb, prefix + INDENT + INDENT); } } diff --git a/Starship/Rockstar.Engine/Statements/Decrement.cs b/Starship/Rockstar.Engine/Statements/Decrement.cs index 984fb23..9eb2cea 100644 --- a/Starship/Rockstar.Engine/Statements/Decrement.cs +++ b/Starship/Rockstar.Engine/Statements/Decrement.cs @@ -6,8 +6,8 @@ namespace Rockstar.Engine.Statements; public class Decrement(Variable v, int multiple, Source source) : Statement(source) { public Variable Variable => v; public int Multiple => multiple; - public override void Print(StringBuilder sb, int depth = 0) { - sb.Indent(depth).AppendLine($"decrement x {multiple}"); - v.Print(sb, depth + 1); + public override void Print(StringBuilder sb, string prefix = "") { + sb.Append(prefix).AppendLine($"decrement x {multiple}"); + v.Print(sb, prefix + INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Statements/Increment.cs b/Starship/Rockstar.Engine/Statements/Increment.cs index 11ae75b..dc69583 100644 --- a/Starship/Rockstar.Engine/Statements/Increment.cs +++ b/Starship/Rockstar.Engine/Statements/Increment.cs @@ -6,8 +6,8 @@ namespace Rockstar.Engine.Statements; public class Increment(Variable v, int multiple, Source source) : Statement(source) { public Variable Variable => v; public int Multiple => multiple; - public override void Print(StringBuilder sb, int depth = 0) { - sb.Indent(depth).AppendLine($"increment x {multiple}"); - v.Print(sb, depth + 1); + public override void Print(StringBuilder sb, string prefix = "") { + sb.Append(prefix).AppendLine($"increment x {multiple}"); + v.Print(sb, prefix + INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Statements/Loop.cs b/Starship/Rockstar.Engine/Statements/Loop.cs index cc10c1b..07547ae 100644 --- a/Starship/Rockstar.Engine/Statements/Loop.cs +++ b/Starship/Rockstar.Engine/Statements/Loop.cs @@ -10,11 +10,12 @@ public abstract class Loop(Expression condition, bool compareTo, Block body, Sou public Expression Condition => condition; public Block Body => body; protected abstract string LoopType { get; } - public override void Print(StringBuilder sb, int depth = 0) { - sb.Indent(depth).AppendLine($"{LoopType}:"); - sb.Indent(depth + 1).AppendLine("test:"); - condition.Print(sb, depth + 2); - sb.Indent(depth + 1).AppendLine("then:"); - body.Print(sb, depth + 2); + public override void Print(StringBuilder sb, string prefix = "") { + sb.Append(prefix).AppendLine($"{LoopType}:"); + sb.Append(prefix + " \u2502 " ).AppendLine("test:"); + condition.Print(sb, prefix + " \u2502 " + INDENT); + sb.Append(prefix + " \u2502 ").AppendLine("then:"); + body.Print(sb, prefix + " \u2502 " + INDENT); + sb.AppendLine(prefix + " \u2514".PadRight(40, '\u2500')); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Statements/Output.cs b/Starship/Rockstar.Engine/Statements/Output.cs index 2d3d002..6933606 100644 --- a/Starship/Rockstar.Engine/Statements/Output.cs +++ b/Starship/Rockstar.Engine/Statements/Output.cs @@ -8,8 +8,8 @@ public class Output(Expression expr, Source source) public Expression Expr => expr; public override string ToString() => $"output: {expr}"; - public override void Print(StringBuilder sb, int depth = 0) { - sb.Indent(depth).AppendLine("output:"); - expr.Print(sb, depth + 1); + public override void Print(StringBuilder sb, string prefix = "") { + sb.Append(prefix).AppendLine("output:"); + expr.Print(sb, prefix + INDENT); } } \ No newline at end of file diff --git a/Starship/Rockstar.Engine/Statements/Statement.cs b/Starship/Rockstar.Engine/Statements/Statement.cs index 6dab02b..e2677c3 100644 --- a/Starship/Rockstar.Engine/Statements/Statement.cs +++ b/Starship/Rockstar.Engine/Statements/Statement.cs @@ -3,7 +3,8 @@ namespace Rockstar.Engine.Statements; public abstract class Statement(Source source) { - public abstract void Print(StringBuilder sb, int depth = 0); + public const string INDENT = " "; + public abstract void Print(StringBuilder sb, string prefix = ""); protected string Location => source.Location; } diff --git a/Starship/Rockstar.Engine/Values/Number.cs b/Starship/Rockstar.Engine/Values/Number.cs index dbd7ef5..9abeb0d 100644 --- a/Starship/Rockstar.Engine/Values/Number.cs +++ b/Starship/Rockstar.Engine/Values/Number.cs @@ -15,8 +15,8 @@ public Number(decimal value) : this(value, Source.None) { } public override string ToString() => value.ToString(CultureInfo.InvariantCulture); - //public override void Print(StringBuilder sb, int depth) - // => sb.Indent(depth).AppendLine($"number: {value:G29} {Location}"); + //public override void Print(StringBuilder sb, string prefix) + // => sb.Append(prefix).AppendLine($"number: {value:G29} {Location}"); public override bool Truthy => value != 0m; diff --git "a/Starship/Rockstar.Engine/Values/Str\303\257ng.cs" "b/Starship/Rockstar.Engine/Values/Str\303\257ng.cs" index 93460e8..b872956 100644 --- "a/Starship/Rockstar.Engine/Values/Str\303\257ng.cs" +++ "b/Starship/Rockstar.Engine/Values/Str\303\257ng.cs" @@ -6,8 +6,8 @@ public class Strïng(string value, Source source) : Value(source) { public Strïng(string value) : this(value, Source.None) { } public string Value => value; - public override void Print(StringBuilder sb, int depth) - => sb.Indent(depth).AppendLine($"string: \"{value}\""); + public override void Print(StringBuilder sb, string prefix) + => sb.Append(prefix).AppendLine($"string: \"{value}\""); public override bool Truthy => !String.IsNullOrEmpty(value); diff --git a/Starship/Rockstar.Engine/Values/Value.cs b/Starship/Rockstar.Engine/Values/Value.cs index 3b0bdff..42e4237 100644 --- a/Starship/Rockstar.Engine/Values/Value.cs +++ b/Starship/Rockstar.Engine/Values/Value.cs @@ -27,8 +27,8 @@ public abstract class Value(Source source) public override string ToString() => ToStrïng().Value; - public override void Print(StringBuilder sb, int depth) - => sb.Indent(depth).AppendLine($"{this.GetType().Name.ToLowerInvariant()}: {this.ToStrïng().Value}"); + public override void Print(StringBuilder sb, string prefix) + => sb.Append(prefix).AppendLine($"{this.GetType().Name.ToLowerInvariant()}: {this.ToStrïng().Value}"); public Strïng ToStrïng() => this switch { diff --git a/Starship/Rockstar.Engine/rockstar.peg b/Starship/Rockstar.Engine/rockstar.peg index 669aa7c..827fb1c 100644 --- a/Starship/Rockstar.Engine/rockstar.peg +++ b/Starship/Rockstar.Engine/rockstar.peg @@ -47,7 +47,6 @@ statement / increment / decrement - noise = (_ / [;,]) increment diff --git a/Starship/Rockstar.Test/ConditionalTests.cs b/Starship/Rockstar.Test/ConditionalTests.cs index 1aa5013..281b5fc 100644 --- a/Starship/Rockstar.Test/ConditionalTests.cs +++ b/Starship/Rockstar.Test/ConditionalTests.cs @@ -13,6 +13,24 @@ say done """)] public void ParserParsesLoop(string source) => Parse(source); + [Theory] + [InlineData(""" + Say "begin" + X is 10 + While X is greater than nothing + Y is 0 + While Y is less than 3 + Build Y up + Say Y + + Knock X down + Say X + + Say "end" + + """)] + public void ParserParsesNestedLoop(string source) => Parse(source); + [Fact] public void WhileLoopWorks() { var source = """ diff --git a/Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject b/Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject index e0aae56..ff82804 100644 --- a/Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject +++ b/Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject @@ -1,5 +1,10 @@  5000 + + + Rockstar.Test.FixtureTests + + \ No newline at end of file