started transitioning RollExpression parsing into a tokenized oo approach
This commit is contained in:
parent
7af123f5d4
commit
491494600d
3 changed files with 132 additions and 53 deletions
87
Lexer.cs
Normal file
87
Lexer.cs
Normal 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
44
Roll.cs
Normal 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
52
Util.cs
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Reference in a new issue