@@ -1,6 +1,7 @@
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Linq ;
using System.Reflection ;
using System.Text.RegularExpressions ;
@@ -8,8 +9,7 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// Interpreter for Property Definition Tree (PDT) file format.
/// </summary>
/// <typeparam name="T">The object type represented by the PDT.</typeparam>
public partial class PdtInterpreter < T > {
public partial class PdtInterpreter {
/// <summary>
/// The character category map.
/// </summary>
@@ -44,34 +44,35 @@ namespace Cryville.Common.Pdt {
/// </summary>
/// <param name="src">The source string.</param>
/// <returns>The interpreted object.</returns>
public static T Interpret ( string src ) {
return Interpret ( src , BinderAttribute . CreateBinderOfType ( typeof ( T ) ) ) ;
public static T Interpret < T > (string src ) {
return Interpret < T > (src , BinderAttribute . CreateBinderOfType ( typeof ( T ) ) ) ;
}
/// <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>
/// <param name="src">The source string.</param>
/// <param name="binder">The binder.</param>
/// <returns>The interpreted object.</returns>
public static T Interpret ( string src , Binder binder ) {
return new PdtInterpreter < T > ( src , binder ) . Interpret ( ) ;
public static T Interpret < T > (string src , Binder binder ) {
return ( T ) new PdtInterpreter ( src , typeof ( T ) , binder ) . Interpret ( ) ;
}
readonly string _src ;
public string Source { get ; private set ; }
readonly Type _type ;
readonly Binder _binder ;
protected int Position { get ; private set ; }
public int Position { get ; private set ; }
#pragma warning disable IDE1006
protected char cc { get { return _s rc[ Position ] ; } }
protected char cc { get { return Sou rce [ Position ] ; } }
protected int ct { get { return cm [ cc ] ; } }
protected string tokenb ( int flag ) { // Token Whitelist
int sp = Position ;
while ( ( ct & flag ) = = 0 ) Position + + ;
return _s rc. Substring ( sp , Position - sp ) ;
return Sou rce . Substring ( sp , Position - sp ) ;
}
protected string tokenw ( int flag ) { // Token Whitelist
int sp = Position ;
while ( ( ct & flag ) ! = 0 ) Position + + ;
return _s rc. Substring ( sp , Position - sp ) ;
return Sou rce . Substring ( sp , Position - sp ) ;
}
protected void ws ( ) {
while ( ( ct & 0x0001 ) ! = 0 ) Position + + ;
@@ -97,7 +98,7 @@ namespace Cryville.Common.Pdt {
Position + + ;
} while ( ct ! = 0x0100 ) ;
Position + + ;
return Regex . Replace ( _s rc. Substring ( sp + 1 , Position - sp - 2 ) , @"\\(.)" , "$1" ) ;
return Regex . Replace ( Sou rce . Substring ( sp + 1 , Position - sp - 2 ) , @"\\(.)" , "$1" ) ;
}
protected PdtExpression GetExp ( ) {
var ins = new LinkedList < PdtInstruction > ( ) ;
@@ -108,23 +109,30 @@ namespace Cryville.Common.Pdt {
readonly Dictionary < string , PdtExpression > defs = new Dictionary < string , PdtExpression > ( ) ;
/// <summary>
/// Creates an instance of the <see cref="PdtInterpreter{T} " /> class.
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
/// </summary>
/// <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>
public PdtInterpreter ( string src , Binder binder ) {
_s rc = src ;
public PdtInterpreter ( string src , Type type , Binder binder ) {
Sou rce = src ;
_type = type ;
_binder = binder ;
if ( _binder = = null )
_binder = BinderAttribute . CreateBinderOfType ( typeof ( T ) ) ;
_binder = BinderAttribute . CreateBinderOfType ( _ type) ;
}
/// <summary>
/// Interprets the source to an object of type <typeparamref name="T" /> .
/// Interprets the source to an object.
/// </summary>
/// <returns>The interpreted object.</returns>
public T Interpret ( ) {
InterpretDirectives ( ) ;
return ( T ) InterpretObject ( typeof ( T ) ) ;
public object Interpret ( ) {
try {
InterpretDirectives ( ) ;
return InterpretObject ( _type ) ;
}
catch ( Exception ex ) {
throw new PdtParsingException ( this , ex ) ;
}
}
void InterpretDirectives ( ) {
bool flag = false ;
@@ -229,4 +237,36 @@ namespace Cryville.Common.Pdt {
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 )
) ;
}
}
}