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

Commit

Permalink
Parser support for functions and function calls. No returns yet.
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanbeattie committed Jul 9, 2024
1 parent 2c65764 commit f53ec56
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 77 deletions.
4 changes: 4 additions & 0 deletions Starship/Rockstar.Engine/Expressions/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ public virtual void Print(StringBuilder sb, string prefix)
=> sb.Append(prefix).AppendLine(this.GetType().Name.ToLowerInvariant());

protected string Location => source.Location;

public List<Expression> Concat(List<Expression> list)
=> new List<Expression> { this }.Concat(list).ToList();

}
3 changes: 3 additions & 0 deletions Starship/Rockstar.Engine/Expressions/Variable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ protected string NormalizedName
=> String.Join("_", whitespace.Split(Name));

public abstract string Key { get; }

public List<Variable> Concat(List<Variable> list)
=> new List<Variable> { this }.Concat(list).ToList();
}
21 changes: 21 additions & 0 deletions Starship/Rockstar.Engine/Statements/Statement.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using Rockstar.Engine.Expressions;

namespace Rockstar.Engine.Statements;

Expand All @@ -8,3 +9,23 @@ public abstract class Statement(Source source) {
protected string Location => source.Location;
}

public class Function(Variable name, IEnumerable<Variable> args, Block body, Source source)
: Statement(source) {
public override void Print(StringBuilder sb, string prefix = "") {
sb.Append(prefix).Append($"function: {name.Name}(");
sb.Append(String.Join(", ", args.Select(a => a.Name)));
sb.AppendLine(")");
body.Print(sb, prefix + "|" + INDENT);
}
}

public class FunctionCall(Variable name, List<Expression> args, Source source)
: Statement(source) {
public override void Print(StringBuilder sb, string prefix = "") {
sb.Append(prefix).AppendLine($"function call: {name.Name}");
foreach (var arg in args) {
arg.Print(sb, prefix + INDENT);
}
}
}

28 changes: 28 additions & 0 deletions Starship/Rockstar.Engine/rockstar.peg
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,37 @@ statement <Statement>
= loop
/ alternate
/ output_stmt
/ function_call
/ function
/ assign_stmt
/ increment
/ decrement


takes = ('takes' / 'wants')

function <Function>
= name:variable _ takes _ args:variable_list EOS body:statements
{ new Function(name, args, body, state.Source()) }

function_call <FunctionCall>
= name:variable _ 'taking' _ args:expression_list
{ new FunctionCall(name, args, state.Source()) }

expression_list <List<Expression>>
= head:expression _XLS_ tail:expression_list
{ head.Concat(tail) }
/ expr:expression { new List<Expression> { expr } }

_XLS_
= (_? ', and' _ / _? ('&' / ',' / "'n'") _?)

_VLS_ = _XLS_ / _ 'and' _

variable_list <List<Variable>>
= head:variable _VLS_ tail:variable_list
{ head.Concat(tail) }
/ arg:variable { new List<Variable> { arg } }

noise = (_ / [;,])

Expand Down
65 changes: 0 additions & 65 deletions Starship/Rockstar.Test/ConditionalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,6 @@

namespace Rockstar.Test;

public class LoopTests(ITestOutputHelper output) : ParserTestBase(output) {
[Theory]
[InlineData("while true say loop")]
[InlineData("""
while true
say loop1
say loop2
say loop3
say done
""")]
public void ParserParsesLoop(string source) => Parse(source);

[Theory]
[InlineData("""
X is 10
While X is greater than nothing
While Y is less than 3
Build Y up
Say Y
Knock X down
""")]
public void ParserParsesNestedLoop(string source) {
var parsed = Parse(source);
parsed.Statements.Count.ShouldBe(2);
}

[Fact]
public void WhileLoopWorks() {
var source = """
let i be 0
while i is less than 5
say i
build i up
say "finished"
""";
var parsed = Parse(source);
var e = new TestEnvironment();
var i = new Interpreter(e);
var result = i.Exec(parsed);
e.Output.ReplaceLineEndings().ShouldBe("0\n1\n2\n3\n4\nfinished\n".ReplaceLineEndings());
}

[Fact]
public void UntilLoopWorks() {
var source = """
let i be 0
until i is as great as 5
say i
build i up
say "finished"
""";
var parsed = Parse(source);
var e = new TestEnvironment();
var i = new Interpreter(e);
var result = i.Exec(parsed);
e.Output.ReplaceLineEndings().ShouldBe("0\n1\n2\n3\n4\nfinished\n".ReplaceLineEndings());
}

}

public class ConditionalTests(ITestOutputHelper output) {
[Theory]
[InlineData("if true say 1")]
Expand Down
10 changes: 10 additions & 0 deletions Starship/Rockstar.Test/FunLyricTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Rockstar.Test;

public class FunLyricTests(ITestOutputHelper output) : ParserTestBase(output) {

[Theory]
[InlineData("It's more than a feeling (More than a feeling)")]
[InlineData("If it's more than a feeling (More than a feeling) say yeah")]
public void ParserParsesLyric(string source)
=> Parse(source);
}
23 changes: 23 additions & 0 deletions Starship/Rockstar.Test/FunctionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Rockstar.Test;

public class FunctionTests(ITestOutputHelper output) : ParserTestBase(output) {
[Theory]
[InlineData("""
Echo takes X
say X
(end function)
""")]
[InlineData("sum taking 2, 3")]
[InlineData("""
Echo takes X
say X
(end function)
Echo taking true
Echo taking "hello world"
put 5 into Temp
Echo taking Temp
""")]
public void ParserParsesFunctions(string source) {
var result = Parse(source);
}
}
66 changes: 66 additions & 0 deletions Starship/Rockstar.Test/LoopTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace Rockstar.Test;

public class LoopTests(ITestOutputHelper output) : ParserTestBase(output) {
[Theory]
[InlineData("while true say loop")]
[InlineData("""
while true
say loop1
say loop2
say loop3
say done
""")]
public void ParserParsesLoop(string source) => Parse(source);

[Theory]
[InlineData("""
X is 10
While X is greater than nothing
While Y is less than 3
Build Y up
Say Y
Knock X down
""")]
public void ParserParsesNestedLoop(string source) {
var parsed = Parse(source);
parsed.Statements.Count.ShouldBe(2);
}

[Fact]
public void WhileLoopWorks() {
var source = """
let i be 0
while i is less than 5
say i
build i up
say "finished"
""";
var parsed = Parse(source);
var e = new TestEnvironment();
var i = new Interpreter(e);
var result = i.Exec(parsed);
e.Output.ReplaceLineEndings().ShouldBe("0\n1\n2\n3\n4\nfinished\n".ReplaceLineEndings());
}

[Fact]
public void UntilLoopWorks() {
var source = """
let i be 0
until i is as great as 5
say i
build i up
say "finished"
""";
var parsed = Parse(source);
var e = new TestEnvironment();
var i = new Interpreter(e);
var result = i.Exec(parsed);
e.Output.ReplaceLineEndings().ShouldBe("0\n1\n2\n3\n4\nfinished\n".ReplaceLineEndings());
}

}
9 changes: 0 additions & 9 deletions Starship/Rockstar.Test/ParserTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,4 @@ protected Block Parse(string source) {
output.WriteLine(result.ToString());
return result;
}
}

public class FunLyricTests(ITestOutputHelper output) : ParserTestBase(output) {

[Theory]
[InlineData("It's more than a feeling (More than a feeling)")]
[InlineData("If it's more than a feeling (More than a feeling) say yeah")]
public void ParserParsesLyric(string source)
=> Parse(source);
}
3 changes: 0 additions & 3 deletions Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
<FixtureTestSelector>
<FixtureName>Rockstar.Test.FixturePreTests</FixtureName>
</FixtureTestSelector>
<FixtureTestSelector>
<FixtureName>Rockstar.Test.FixtureTests</FixtureName>
</FixtureTestSelector>
</IgnoredTests>
</Settings>
</ProjectConfiguration>

0 comments on commit f53ec56

Please sign in to comment.