Add exception description on PDT parsing error.
This commit is contained in:
@@ -91,7 +91,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public partial class PdtInterpreter<T> {
|
public partial class PdtInterpreter {
|
||||||
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
|
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
|
||||||
{ '@', 7 },
|
{ '@', 7 },
|
||||||
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
@@ -8,8 +9,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interpreter for Property Definition Tree (PDT) file format.
|
/// Interpreter for Property Definition Tree (PDT) file format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The object type represented by the PDT.</typeparam>
|
public partial class PdtInterpreter {
|
||||||
public partial class PdtInterpreter<T> {
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The character category map.
|
/// The character category map.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,34 +44,35 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">The source string.</param>
|
/// <param name="src">The source string.</param>
|
||||||
/// <returns>The interpreted object.</returns>
|
/// <returns>The interpreted object.</returns>
|
||||||
public static T Interpret(string src) {
|
public static T Interpret<T>(string src) {
|
||||||
return Interpret(src, BinderAttribute.CreateBinderOfType(typeof(T)));
|
return Interpret<T>(src, BinderAttribute.CreateBinderOfType(typeof(T)));
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interprets a source string to an object of type <typeparamref name="T" /> with a binder.
|
/// Interprets a source string to an object of type <typeparamref name="T"/> with a binder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">The source string.</param>
|
/// <param name="src">The source string.</param>
|
||||||
/// <param name="binder">The binder.</param>
|
/// <param name="binder">The binder.</param>
|
||||||
/// <returns>The interpreted object.</returns>
|
/// <returns>The interpreted object.</returns>
|
||||||
public static T Interpret(string src, Binder binder) {
|
public static T Interpret<T>(string src, Binder binder) {
|
||||||
return new PdtInterpreter<T>(src, binder).Interpret();
|
return (T)new PdtInterpreter(src, typeof(T), binder).Interpret();
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly string _src;
|
public string Source { get; private set; }
|
||||||
|
readonly Type _type;
|
||||||
readonly Binder _binder;
|
readonly Binder _binder;
|
||||||
protected int Position { get; private set; }
|
public int Position { get; private set; }
|
||||||
#pragma warning disable IDE1006
|
#pragma warning disable IDE1006
|
||||||
protected char cc { get { return _src[Position]; } }
|
protected char cc { get { return Source[Position]; } }
|
||||||
protected int ct { get { return cm[cc]; } }
|
protected int ct { get { return cm[cc]; } }
|
||||||
protected string tokenb(int flag) { // Token Whitelist
|
protected string tokenb(int flag) { // Token Whitelist
|
||||||
int sp = Position;
|
int sp = Position;
|
||||||
while ((ct & flag) == 0) Position++;
|
while ((ct & flag) == 0) Position++;
|
||||||
return _src.Substring(sp, Position - sp);
|
return Source.Substring(sp, Position - sp);
|
||||||
}
|
}
|
||||||
protected string tokenw(int flag) { // Token Whitelist
|
protected string tokenw(int flag) { // Token Whitelist
|
||||||
int sp = Position;
|
int sp = Position;
|
||||||
while ((ct & flag) != 0) Position++;
|
while ((ct & flag) != 0) Position++;
|
||||||
return _src.Substring(sp, Position - sp);
|
return Source.Substring(sp, Position - sp);
|
||||||
}
|
}
|
||||||
protected void ws() {
|
protected void ws() {
|
||||||
while ((ct & 0x0001) != 0) Position++;
|
while ((ct & 0x0001) != 0) Position++;
|
||||||
@@ -97,7 +98,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
Position++;
|
Position++;
|
||||||
} while (ct != 0x0100);
|
} while (ct != 0x0100);
|
||||||
Position++;
|
Position++;
|
||||||
return Regex.Replace(_src.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1");
|
return Regex.Replace(Source.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1");
|
||||||
}
|
}
|
||||||
protected PdtExpression GetExp() {
|
protected PdtExpression GetExp() {
|
||||||
var ins = new LinkedList<PdtInstruction>();
|
var ins = new LinkedList<PdtInstruction>();
|
||||||
@@ -108,23 +109,30 @@ namespace Cryville.Common.Pdt {
|
|||||||
|
|
||||||
readonly Dictionary<string, PdtExpression> defs = new Dictionary<string, PdtExpression>();
|
readonly Dictionary<string, PdtExpression> defs = new Dictionary<string, PdtExpression>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of the <see cref="PdtInterpreter{T}" /> class.
|
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">The source string.</param>
|
/// <param name="src">The source string.</param>
|
||||||
|
/// <param name="type">The destination type.</param>
|
||||||
/// <param name="binder">The binder. May be <c>null</c>.</param>
|
/// <param name="binder">The binder. May be <c>null</c>.</param>
|
||||||
public PdtInterpreter(string src, Binder binder) {
|
public PdtInterpreter(string src, Type type, Binder binder) {
|
||||||
_src = src;
|
Source = src;
|
||||||
|
_type = type;
|
||||||
_binder = binder;
|
_binder = binder;
|
||||||
if (_binder == null)
|
if (_binder == null)
|
||||||
_binder = BinderAttribute.CreateBinderOfType(typeof(T));
|
_binder = BinderAttribute.CreateBinderOfType(_type);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interprets the source to an object of type <typeparamref name="T" />.
|
/// Interprets the source to an object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The interpreted object.</returns>
|
/// <returns>The interpreted object.</returns>
|
||||||
public T Interpret() {
|
public object Interpret() {
|
||||||
InterpretDirectives();
|
try {
|
||||||
return (T)InterpretObject(typeof(T));
|
InterpretDirectives();
|
||||||
|
return InterpretObject(_type);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new PdtParsingException(this, ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void InterpretDirectives() {
|
void InterpretDirectives() {
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
@@ -229,4 +237,36 @@ namespace Cryville.Common.Pdt {
|
|||||||
return tokenb(0x1000).Trim();
|
return tokenb(0x1000).Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The exception that is thrown when the interpretation of a PDT fails.
|
||||||
|
/// </summary>
|
||||||
|
public class PdtParsingException : Exception {
|
||||||
|
public PdtParsingException(PdtInterpreter interpreter) : this(interpreter, null) { }
|
||||||
|
public PdtParsingException(PdtInterpreter interpreter, Exception innerException)
|
||||||
|
: base(GenerateMessage(interpreter, innerException), innerException) { }
|
||||||
|
static string GenerateMessage(PdtInterpreter interpreter, Exception innerException) {
|
||||||
|
string src = interpreter.Source;
|
||||||
|
int pos = interpreter.Position;
|
||||||
|
if (pos >= src.Length) return "Failed to interpret the PDT: There are some missing or redundant tokens";
|
||||||
|
int lineStartPos = src.LastIndexOf('\n', pos) + 1;
|
||||||
|
int previewStartPos = src.LastIndexOf('\n', pos, 64);
|
||||||
|
if (previewStartPos == -1) {
|
||||||
|
previewStartPos = pos - 64;
|
||||||
|
if (previewStartPos < 0) previewStartPos = 0;
|
||||||
|
}
|
||||||
|
else previewStartPos++;
|
||||||
|
int previewEndPos = src.IndexOf('\n', pos, 64);
|
||||||
|
if (previewEndPos == -1) {
|
||||||
|
previewEndPos = pos + 64;
|
||||||
|
if (previewEndPos > src.Length) previewEndPos = src.Length;
|
||||||
|
}
|
||||||
|
return string.Format(
|
||||||
|
"Failed to interpret the PDT at line {0}, position {1}: {2}\n{3}",
|
||||||
|
src.Take(interpreter.Position).Count(c => c == '\n') + 1,
|
||||||
|
pos - lineStartPos + 1,
|
||||||
|
innerException == null ? "Unknown error" : innerException.Message,
|
||||||
|
src.Substring(previewStartPos, previewEndPos - previewStartPos)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Cryville.Crtr {
|
|||||||
public void LoadPdt(DirectoryInfo dir) {
|
public void LoadPdt(DirectoryInfo dir) {
|
||||||
using (StreamReader pdtreader = new StreamReader(dir.FullName + "/" + data + ".pdt", Encoding.UTF8)) {
|
using (StreamReader pdtreader = new StreamReader(dir.FullName + "/" + data + ".pdt", Encoding.UTF8)) {
|
||||||
var src = pdtreader.ReadToEnd();
|
var src = pdtreader.ReadToEnd();
|
||||||
Root = new RulesetInterpreter(src, null).Interpret();
|
Root = (PdtRuleset)new RulesetInterpreter(src, null).Interpret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using System.Collections.Generic;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
internal class RulesetInterpreter : PdtInterpreter<PdtRuleset> {
|
internal class RulesetInterpreter : PdtInterpreter {
|
||||||
public RulesetInterpreter(string src, Binder binder) : base(src, binder) { }
|
public RulesetInterpreter(string src, Binder binder) : base(src, typeof(PdtRuleset), binder) { }
|
||||||
|
|
||||||
readonly List<RulesetSelector> s = new List<RulesetSelector>();
|
readonly List<RulesetSelector> s = new List<RulesetSelector>();
|
||||||
readonly List<string> a = new List<string>();
|
readonly List<string> a = new List<string>();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Cryville.Crtr {
|
|||||||
public void LoadPdt(DirectoryInfo dir) {
|
public void LoadPdt(DirectoryInfo dir) {
|
||||||
using (StreamReader pdtreader = new StreamReader(dir.FullName + "/" + data + ".pdt", Encoding.UTF8)) {
|
using (StreamReader pdtreader = new StreamReader(dir.FullName + "/" + data + ".pdt", Encoding.UTF8)) {
|
||||||
var src = pdtreader.ReadToEnd();
|
var src = pdtreader.ReadToEnd();
|
||||||
Root = new SkinInterpreter(src, null).Interpret();
|
Root = (PdtSkin)new SkinInterpreter(src, null).Interpret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ using System.Collections.Generic;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class SkinInterpreter : PdtInterpreter<PdtSkin> {
|
public class SkinInterpreter : PdtInterpreter {
|
||||||
public SkinInterpreter(string src, Binder binder) : base(src, binder) { }
|
public SkinInterpreter(string src, Binder binder) : base(src, typeof(PdtSkin), binder) { }
|
||||||
|
|
||||||
readonly List<SkinSelector> s = new List<SkinSelector>();
|
readonly List<SkinSelector> s = new List<SkinSelector>();
|
||||||
readonly List<string> a = new List<string>();
|
readonly List<string> a = new List<string>();
|
||||||
|
|||||||
Reference in New Issue
Block a user