2016-05-07 19:03:44 +00:00
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Text.RegularExpressions ;
2016-05-07 19:31:15 +00:00
using System.Diagnostics ;
using System.IO ;
2016-08-04 11:15:15 +00:00
using System.Runtime.ConstrainedExecution ;
2016-05-07 19:03:44 +00:00
namespace cscz
{
2016-06-27 20:09:45 +00:00
public enum GenerationMode
{
PrivateVariablesWithProperties ,
2016-10-18 11:51:25 +00:00
PublicVariables ,
PublicAutoProperties
2016-06-27 20:09:45 +00:00
}
2016-05-07 19:03:44 +00:00
public class ClassGenerator
{
/// <summary>
/// A mapping of namespaces to using shortcuts.
/// </summary>
public Dictionary < string , string > UsingShortcuts = new Dictionary < string , string > ( )
{
2016-08-04 11:18:50 +00:00
["c"] = "System.Collections.Generic" ,
["cc"] = "System.Collections.Concurrent" ,
["r"] = "System.Text.RegularExpressions" ,
["n"] = "System.Net" ,
["s"] = "System.Net.Sockets" ,
["x"] = "Microsoft.Xna.Framework" ,
["xg"] = "Microsoft.Xna.Framework.Graphics" ,
["xs"] = "Microsoft.Xna.Framework.Storage" ,
["xi"] = "Microsoft.Xna.Framework.Input" ,
["oo"] = "OpenTK.Graphics.OpenGL"
2016-05-07 19:03:44 +00:00
} ;
/// <summary>
/// The using statements to add to the generated class.
/// </summary>
public List < string > UsingStatements = new List < string > ( )
{
2016-06-27 19:39:14 +00:00
"System"
2016-05-07 19:03:44 +00:00
} ;
public List < string > Signatures = new List < string > ( ) ;
public string ClassName = "Carrot" ;
2016-08-04 11:15:15 +00:00
public string Namespace = string . Empty ;
2016-05-07 19:03:44 +00:00
2016-06-27 20:09:45 +00:00
public GenerationMode GenerationMode = GenerationMode . PublicVariables ;
2016-05-07 19:03:44 +00:00
/// <summary>
/// Whether to make data members private and create public properties for them instead of making the
/// data members public.
2016-06-27 20:09:45 +00:00
/// This is read only. Please refer to GenerationMode in order to change this field.
2016-05-07 19:03:44 +00:00
/// </summary>
2016-06-27 20:09:45 +00:00
public bool CreateProperties
{
get
{
if ( GenerationMode = = GenerationMode . PrivateVariablesWithProperties )
return true ;
return false ;
}
}
2016-05-07 19:03:44 +00:00
public ClassGenerator ( )
{
}
2016-05-07 19:31:15 +00:00
public void ParseString ( string source )
{
StringReader lines = new StringReader ( source ) ;
string nextLine = string . Empty ;
do {
nextLine = lines . ReadLine ( ) ;
if ( nextLine = = null ) break ;
2016-05-08 10:39:56 +00:00
if ( nextLine . Length = = 0 ) continue ;
2016-05-07 19:31:15 +00:00
2016-08-04 10:49:57 +00:00
nextLine = nextLine . Trim ( ) ;
2016-05-07 19:31:15 +00:00
// It's a using statement
2016-08-04 10:49:57 +00:00
if ( nextLine . StartsWith ( "- " ) )
2016-05-07 19:31:15 +00:00
{
2016-08-04 10:49:57 +00:00
string [ ] parts = Regex . Split ( nextLine , @"\s+" ) ;
2016-05-07 19:31:15 +00:00
UsingStatements . Add ( parts [ 1 ] ) ;
}
2016-05-08 10:39:56 +00:00
else if ( nextLine . StartsWith ( "#" ) )
{
// It's the class name
ClassName = UppercaseFirstLetter ( nextLine . TrimStart ( new char [ ] { '#' } ) ) . Trim ( ) ;
2016-08-04 11:15:15 +00:00
// Parse the namespace, if one is present
if ( ClassName . Contains ( "." ) )
{
Namespace = ClassName . Substring ( 0 , ClassName . LastIndexOf ( "." ) ) ;
ClassName = ClassName . Substring ( ClassName . LastIndexOf ( "." ) + 1 ) ;
}
2016-05-08 10:39:56 +00:00
}
2016-05-07 19:31:15 +00:00
else
{
Signatures . Add ( nextLine . Trim ( ) ) ;
}
} while ( nextLine ! = null ) ;
}
2016-05-07 19:03:44 +00:00
public override string ToString ( )
{
2016-08-04 11:15:15 +00:00
StringWriter usingStatements = new StringWriter ( ) ;
2016-07-25 18:22:22 +00:00
2016-08-04 11:15:15 +00:00
// Generate the using statements
2016-05-07 19:03:44 +00:00
foreach ( string usingStatement in UsingStatements )
2016-08-04 11:15:15 +00:00
usingStatements . WriteLine ( "using {0};" , expandUsingShortcut ( usingStatement ) ) ;
// Generate the class itself
StringWriter classCode = new StringWriter ( ) ;
2016-07-25 18:22:22 +00:00
// Class name
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( "class {0} " , ClassName ) ;
classCode . WriteLine ( "{" ) ;
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Class body parts declaration
2016-08-04 11:15:15 +00:00
StringBuilder constructorSignature = new StringBuilder ( string . Format ( "\tpublic {0}(" , ClassName ) ) ; // This has to be a StringBuilder because of the Remove() class later on
StringWriter properties = new StringWriter ( ) ;
StringWriter constructorBody = new StringWriter ( ) ;
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Data member signature handling
2016-05-07 19:03:44 +00:00
foreach ( string signature in Signatures )
{
2016-07-25 18:22:22 +00:00
string [ ] signatureParts = Regex . Split ( signature , @"\s+" ) ;
string datatypeName = signatureParts [ 0 ] ;
string privateDataMemberName = LowercaseFirstLetter ( signatureParts [ 1 ] ) ;
string publicDataMemberName = UppercaseFirstLetter ( signatureParts [ 1 ] ) ;
2016-05-07 19:03:44 +00:00
constructorSignature . AppendFormat ( "{0} in{1}, " , datatypeName , publicDataMemberName ) ;
if ( CreateProperties )
{
2016-07-25 18:22:22 +00:00
// Private data member
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( "\tprivate {0} {1};" , datatypeName , privateDataMemberName ) ;
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Public property associated with above private data member
2016-08-04 11:15:15 +00:00
properties . WriteLine ( "\tpublic {0} {1}" , datatypeName , publicDataMemberName ) ;
2016-08-10 08:35:39 +00:00
properties . WriteLine ( "\t{" ) ;
2016-08-04 11:15:15 +00:00
properties . WriteLine ( "\t\tget {{ return {0}; }}" , privateDataMemberName ) ;
properties . WriteLine ( "\t\tset {{ {0} = value; }}" , privateDataMemberName ) ;
2016-08-10 08:35:39 +00:00
properties . WriteLine ( "\t}" ) ;
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Constructor body
2016-08-04 11:15:15 +00:00
constructorBody . WriteLine ( "\t\t{0} = in{0};" , publicDataMemberName ) ;
2016-05-07 19:03:44 +00:00
}
else
{
2016-07-25 18:22:22 +00:00
// Constuctor body
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( "\tpublic {0} {1};" , datatypeName , publicDataMemberName ) ;
constructorBody . WriteLine ( "\t\t{0} = in{0};" , publicDataMemberName ) ;
2016-05-07 19:03:44 +00:00
}
}
// Add the properties to the output
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( properties . ToString ( ) ) ;
2016-05-07 19:03:44 +00:00
// Add the constructor to the output
constructorSignature . Remove ( constructorSignature . Length - 2 , 2 ) ; // Remove the last ", "
constructorSignature . Append ( ")" ) ;
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( constructorSignature . ToString ( ) ) ;
classCode . WriteLine ( "\t{" ) ;
classCode . Write ( constructorBody . ToString ( ) ) ;
classCode . WriteLine ( "\t}" ) ;
2016-05-07 19:03:44 +00:00
// Close the class off and end the file
2016-08-04 11:15:15 +00:00
classCode . WriteLine ( "}" ) ;
StringWriter result = new StringWriter ( ) ;
result . WriteLine ( usingStatements ) ;
if ( Namespace = = string . Empty )
{
result . WriteLine ( classCode ) ;
}
else
{
result . WriteLine ( "namespace {0}" , Namespace ) ;
result . WriteLine ( "{" ) ;
result . WriteLine ( "\t" + classCode . ToString ( ) . Replace ( "\n" , "\n\t" ) ) ;
result . WriteLine ( "}" ) ;
}
2016-05-07 19:03:44 +00:00
return result . ToString ( ) ;
}
protected string expandUsingShortcut ( string shortcut )
{
if ( UsingShortcuts . ContainsKey ( shortcut ) )
return UsingShortcuts [ shortcut ] ;
else
return shortcut ;
}
private string UppercaseFirstLetter ( string str )
{
if ( str = = null )
return null ;
if ( str . Length > 1 )
return char . ToUpper ( str [ 0 ] ) + str . Substring ( 1 ) ;
return str . ToUpper ( ) ;
}
private string LowercaseFirstLetter ( string str )
{
if ( str = = null )
return null ;
if ( str . Length > 1 )
return char . ToLower ( str [ 0 ] ) + str . Substring ( 1 ) ;
return str . ToLower ( ) ;
}
}
2016-10-18 11:51:25 +00:00
}