started transitioning RollExpression parsing into a tokenized oo approach

This commit is contained in:
Valerie Wolfe 2024-03-31 21:02:02 -04:00
parent 7af123f5d4
commit 491494600d
3 changed files with 132 additions and 53 deletions

87
Lexer.cs Normal file
View file

@ -0,0 +1,87 @@
using System.Text.RegularExpressions;
namespace Dungeoneer.Lexing {
public abstract class Token {
public virtual string Format() { return Expression(); }
public abstract string Expression();
}
public class LiteralToken : Token {
public string Content { get; private set; }
public LiteralToken(string text) { Content = text; }
public override string Expression() { return Content; }
}
public class DiceToken : Token {
public int Count { get; private set; }
public int Sides { get; private set; }
private List<int> _result = null;
public List<int> Result {
get {
if(_result == null) {
_result = new List<int>();
for(int i = 0; i < Count; i++)
_result.Add(Util.Roll(Sides));
}
return _result;
}
}
public int? _sum = null;
public int Sum {
get {
if(!_sum.HasValue) {
_sum = 0;
foreach(var roll in Result)
_sum += roll;
}
return _sum.Value;
}
}
public DiceToken(int count, int sides) {
Count = count;
Sides = sides;
}
public DiceToken(Match match) {
Count = int.Parse(match.Groups[1].Value);
Sides = int.Parse(match.Groups[2].Value);
}
private const string Style = "\x1b[34;1m";
private static readonly Regex Pattern = new Regex(@"(\d+)d(\d+)");
public override string Format() {
var output = $"{Style}( ";
var result = Result;
for(int i = 0; i < Count; i++)
if(i < Count - 1)
output += $"{result[i]}, ";
else
output += $"{result[i]} ){Dungeoneer.Format.Reset}";
return output;
}
public override string Expression() { return Sum.ToString(); }
public static Match Match(string text) { return Pattern.Match(text); }
}
/*public class DcToken : Token {
private const string Style = "\x1b[31m";
private static readonly Regex Pattern = new Regex(@"dc\:(\d+)");
public static Match Match(string text) { return Pattern.Match(text); }
public override string Expression() { return ""; }
}*/
}

44
Roll.cs Normal file
View file

@ -0,0 +1,44 @@
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using Dungeoneer.Lexing;
namespace Dungeoneer {
public class RollExpression {
private IList<string> Parts;
public string Print { get; private set; }
public string Expression { get; private set; }
public dynamic Result {
get {
try { return Scripting.Expr($"eval('{Expression}')"); }
catch { return null; }
}
}
public RollExpression(IList<string> parts) {
this.Parts = parts;
this.Print = "";
this.Expression = "";
// build expression from string parts
foreach(string piece in Parts) {
// die expression substitution
var dieCheck = DiceToken.Match(piece);
if(dieCheck.Success) {
var token = new DiceToken(dieCheck);
this.Print += $"{token.Format()} ";
this.Expression += $"{token.Expression()} ";
} else {
var part = $"{piece} ";
this.Expression += part;
this.Print += part;
}
}
}
}
}

52
Util.cs
View file

@ -1,5 +1,4 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace Dungeoneer { namespace Dungeoneer {
@ -11,57 +10,6 @@ namespace Dungeoneer {
} }
public class RollExpression {
private IList<string> Parts;
public string Print { get; private set; }
public string Expression { get; private set; }
public dynamic Result {
get {
try { return Scripting.Expr($"eval('{Expression}')"); }
catch { return null; }
}
} }
private const string DieFormat = "\x1b[34;1m";
private static readonly Regex DiePattern = new Regex(@"(\d+)d(\d+)");
public RollExpression(IList<string> parts) {
this.Parts = parts;
this.Print = "";
this.Expression = "";
// build expression from string parts
foreach(string piece in Parts) {
// die expression substitution
var dieCheck = DiePattern.Match(piece);
if(dieCheck.Success) {
// get /(d+)/ capture group values
var count = int.Parse(dieCheck.Groups[1].Value);
var sides = int.Parse(dieCheck.Groups[2].Value);
// and build roll outcomes
this.Print += $"{DieFormat}( ";
this.Expression += "( ";
for(int i = 0; i < count; i++) {
var roll = Util.Roll(sides);
if(i < count - 1) {
this.Print += $"{roll}, ";
this.Expression += $"{roll} + ";
} else {
var part = $"{roll} ";
this.Print += $"{roll} ){Format.Reset} ";
this.Expression += $"{roll} ) ";
}
}
} else {
var part = $"{piece} ";
this.Expression += part;
this.Print += part;
}
}
}
}
}