Skip to content
This repository has been archived by the owner on Oct 12, 2024. It is now read-only.

Commit

Permalink
Variable name normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanbeattie committed Jul 5, 2024
1 parent 52b521d commit 76c2714
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 18 deletions.
28 changes: 26 additions & 2 deletions Starship/Rockstar.Engine/Expressions/Variable.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
using System.Text;
using System.Text.RegularExpressions;

namespace Rockstar.Engine.Expressions;

public class Variable(string name, Source source) : Expression(source) {

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}");
}
}

protected static Regex whitespace = new("\\s+", RegexOptions.Compiled);

protected string NormalizedName
=> String.Join("_", whitespace.Split(Name));

public abstract string Key { get; }
}

public class SimpleVariable(string name, Source source) : Variable(name, source) {
public SimpleVariable(string name) : this(name, Source.None) { }
public override string Key => Name.ToLowerInvariant();
}

public class ProperVariable(string name, Source source) : Variable(name, source) {
public ProperVariable(string name) : this(name, Source.None) { }
public override string Key => NormalizedName.ToUpperInvariant();
}

public class CommonVariable(string name, Source source) : Variable(name, source) {
public CommonVariable(string name) : this(name, Source.None) { }
public override string Key => NormalizedName.ToLowerInvariant();
}
4 changes: 2 additions & 2 deletions Starship/Rockstar.Engine/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ private Result Output(Output output) {
Binary binary => binary.Resolve(Eval),

// not sure what the difference is here.... ?
Looküp lookup => env.GetVariable(lookup.Variable.Name),
Variable v => env.GetVariable(v.Name),
Looküp lookup => env.GetVariable(lookup.Variable),
Variable v => env.GetVariable(v),
Unary u => u switch {
{ Op: Operator.Minus, Expr: Number n } => n.Negate(),
{ Op: Operator.Not } => Booleän.Not(Eval(u.Expr)),
Expand Down
8 changes: 6 additions & 2 deletions Starship/Rockstar.Engine/RockstarEnvironment.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Rockstar.Engine.Expressions;
using Rockstar.Engine.Values;

namespace Rockstar.Engine;
Expand All @@ -8,6 +9,9 @@ public abstract class RockstarEnvironment {
public abstract void Write(string s);

private readonly Dictionary<string, Value> variables = new();
public void SetVariable(string name, Value value) => variables[name.ToLowerInvariant()] = value;
public Value GetVariable(string name) => variables[name.ToLowerInvariant()];
public void SetVariable(Variable variable, Value value) => variables[variable.Key] = value;

public Value GetVariable(Variable variable) =>
variables.TryGetValue(variable.Key, out var value) ? value : throw new Exception($"Unknown variable '{variable.Name}'");

}
2 changes: 1 addition & 1 deletion Starship/Rockstar.Engine/Statements/Assign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Rockstar.Engine.Statements;

public class Assign(Variable name, Expression expr, Source source)
: Statement(source) {
public string Name => name.Name;
public Variable Name => name;
public Expression Expr => expr;
public override void Print(StringBuilder sb, int depth) {
sb.Indent(depth).AppendLine($"assign:");
Expand Down
18 changes: 10 additions & 8 deletions Starship/Rockstar.Engine/rockstar.peg
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@using Rockstar.Engine.Statements
@using Rockstar.Engine.Expressions
@using Rockstar.Engine.Values;
@trace true

@ignorecase true

Expand All @@ -20,6 +21,8 @@ __ = _? EOS*
EOS = _? EOL _?
EOL = '\r'? '\n'
EOF = !.
// / unexpected:. #error{ "Unexpected character '" + unexpected + "' at line " + state.Line + ", col " + state.Column }


statement <Statement>
= output_stmt
Expand All @@ -43,15 +46,14 @@ output_stmt <Statement>
= output _ e:expression { new Output(e, state.Source()) }

variable <Variable>
= name:variable_name { new Variable(name, state.Source(name)) }
= name:variable_name

variable_name
= common_variable
/ proper_variable
/ simple_variable
variable_name <Variable>
= name:common_variable { new CommonVariable(name, state.Source(name)) }
/ name:proper_variable { new ProperVariable(name, state.Source(name)) }
/ name:simple_variable { new SimpleVariable(name, state.Source(name)) }

proper_variable
// e.g. Big Bad Benny
proper_variable // e.g. Big Bad Benny
= proper_noun (_ proper_noun)*

proper_noun
Expand All @@ -61,7 +63,7 @@ common_variable
= common_prefix _ simple_variable

common_prefix
= 'a' / 'an' / 'the' / 'my' / 'your' / 'our'
= 'an' / 'a' / 'the' / 'my' / 'your' / 'our'

simple_variable
= ("" letter+)
Expand Down
6 changes: 4 additions & 2 deletions Starship/Rockstar.Test/FixtureBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ public override void Write(string s)

public abstract class FixtureBase(ITestOutputHelper testOutput) {

private static string[] ListRockFiles() =>
Directory.GetFiles("fixtures", "*.rock", SearchOption.AllDirectories);
private static string[] excludes = ["arrays", "conditionals", "control-flow", "examples"];
private static IEnumerable<string> ListRockFiles() =>
Directory.GetFiles("fixtures", "*.rock", SearchOption.AllDirectories)
.Where(f => !excludes.Any(f.Contains));

public static IEnumerable<object[]> GetFiles()
=> ListRockFiles().Select(filePath => new[] { filePath });
Expand Down
62 changes: 61 additions & 1 deletion Starship/Rockstar.Test/ParserTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
using System.ComponentModel.Design;
using System.Diagnostics;
using Pegasus.Common.Tracing;
using Rockstar.Engine.Expressions;

namespace Rockstar.Test {
public class ParserTests {

public class VariableTests {
[Theory]
[InlineData("a variable", "a variable")]
[InlineData("My variable", "MY VARIABLE")]
[InlineData("My variable", "MY VARIable")]
[InlineData("My variable", "MY VARIable")]
[InlineData("My variable", "MY\t\tVARIable")]
[InlineData("My variable", "MY VARIable")]
public void CommonVariablesAreCaseInsensitiveAndIgnoreWhitespace(string name1, string name2) {
var a = new CommonVariable(name1);
var b = new CommonVariable(name2);
a.Key.ShouldBe(b.Key);
}

[Theory]
[InlineData("Alpha", "ALPHA")]
[InlineData("beta", "Beta")]
[InlineData("gamma", "GaMmA")]
[InlineData("deLTA", "DElta")]
public void SimpleVariablesAreCaseInsensitiveAndIgnoreWhitespace(string name1, string name2) {
var a = new SimpleVariable(name1);
var b = new SimpleVariable(name2);
a.Key.ShouldBe(b.Key);
}

[Theory]
[InlineData("Mister Crowley", "MISTER CROWLEY")]
[InlineData("Dr Feelgood", "DR Feelgood")]
[InlineData("Black Betty", "BLaCK BeTTY")]
public void ProperVariablesAreCaseInsensitiveAndIgnoreWhitespace(string name1, string name2) {
var a = new ProperVariable(name1);
var b = new ProperVariable(name2);
a.Key.ShouldBe(b.Key);
}
}
public class ParserTests(ITestOutputHelper helper) {
[Theory]
[InlineData("")]
[InlineData(" ")]
Expand Down Expand Up @@ -76,5 +117,24 @@ public void ParserParsesSaysLiterals(string source, int count) {
var result = parser.Parse(source);
result.Statements.Count.ShouldBe(count);
}

[Theory]
[InlineData("an variable is 1", 1)]
[InlineData("""
an variable is 1
""", 1)]
[InlineData("""
a variable is 1
a variable is 2
""", 2)]
public void ParserParsesCommonVariables(string source, int count) {
var parser = new Parser {
Tracer = DiagnosticsTracer.Instance
};
var result = parser.Parse(source);
result.Statements.Count.ShouldBe(count);
}
}
}


0 comments on commit 76c2714

Please sign in to comment.