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.Text.RegularExpressions;
|
||||
|
||||
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