do some preparation work

- establish BMapSharp project for future development.
- refactor EnumsMigration. add csharp code output for it.
- add README for VectorGen and modify other READMEs.
This commit is contained in:
2024-04-22 14:13:36 +08:00
parent c03c80d938
commit 8a1fc03965
20 changed files with 1536 additions and 319 deletions

View File

@ -2,7 +2,7 @@
dest/*
!dest/*.gitkeep
# Antlr output
# ===== ANTLR Output =====
*.interp
*.tokens
@ -10,6 +10,7 @@ CKGeneralLexer*.java
CKEnumsParser*.java
CKDefinesParser*.java
# ===== Eclipse Java =====
# Eclipse projects
.classpath
.project

View File

@ -0,0 +1,168 @@
import java.io.OutputStreamWriter;
/**
* Write enum declarations and accessible value into CSharp format.
*/
public class CSharpWriter {
// =========== C# Enum Declaration Writer ===========
/**
* Get corredponding C# underlying type of given enum.
* <p>
* This is C# specific function.
*
* @param canUnsigned The parameter stored in Enum_t that indicate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
private static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "uint" : "int";
}
/**
* Internal real enum declaration writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CSharp);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
// write flasg attribute if it is
if (enum_t.mUseFlags) {
indent.puts("[Flags]");
}
indent.printf("public enum %s : %s {", enum_t.mEnumName, getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
/**
* Write an enum declaration collection into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum declaration into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create collection from single enum
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== C# Enum Accessible Value Writer ===========
/**
* Internal real enum accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CSharp);
// write enum collections
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf(
"public static readonly System.Collections.Generic.Dictionary<%s, string> %s = new System.Collections.Generic.Dictionary<%s, string>() {",
enum_t.mEnumName, enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ %s.%s, \"%s\" },", enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum accessible value collection into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create a collection with single enum.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col);
fs.close();
}
}

View File

@ -1,28 +0,0 @@
import java.io.OutputStreamWriter;
import java.util.stream.Collectors;
/**
* The nameof values writer for CK_CLASSID.
*/
public class ClassidWriter {
public static void writeAccVal(String filename, EnumsHelper.Enum_t classids) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
indent.puts("const CkClassidReflectionArray CK_CLASSID {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : classids.mEntries) {
EnumsHelper.EnumEntryWithHierarchy_t specialized = (EnumsHelper.EnumEntryWithHierarchy_t) entry;
String hierarchy = specialized.mHierarchy.stream().map(value -> value.mEntryName)
.collect(Collectors.joining("\", \""));
indent.printf("{ LibCmo::CK2::CK_CLASSID::%s, { { \"%s\" } } },", entry.mEntryName, hierarchy);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -4,7 +4,6 @@ import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.antlr.v4.runtime.*;
@ -110,17 +109,6 @@ public class CommonHelper {
return numstr.replaceFirst("[ulUL]+$", "");
}
/**
* Get underlying type of enum.
*
* @param canUnsigned The parameter stored in Enum_t that indiccate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
public static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "CKDWORD" : "CKINT";
}
// =========== Parts ===========
enum CKParts {
@ -128,7 +116,7 @@ public class CommonHelper {
}
enum LangType {
CPP, Python
Cpp, Python, CSharp
}
public static String getCKPartsNamespace(CKParts parts) {

View File

@ -0,0 +1,273 @@
import java.io.OutputStreamWriter;
import java.util.stream.Collectors;
/**
* Write enum declarations and accessible value into C++ format.
*/
public class CppWriter {
// =========== C++ Enum Declaration Writer ===========
/**
* Get corredponding C++ underlying type of given enum.
* <p>
* This is C++ specific function.
*
* @param canUnsigned The parameter stored in Enum_t that indicate whether this
* enum can use unsigned int as its underlying type.
* @return The string form of its underlying type.
*/
private static String getEnumUnderlyingType(boolean canUnsigned) {
return canUnsigned ? "CKDWORD" : "CKINT";
}
/**
* Internal real enum declarations writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
indent.printf("enum class %s : %s {", enum_t.mEnumName, getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum collection into given file.
* <p>
* Actually this is a wrapper of internal enum collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum into given file.
* <p>
* Actually this is a wrapper of internal enum collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create an collection from single enum declaration
// for suit the argument requirement of real writer.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== C++ Enum Accessible Value Writer ===========
/**
* Internal real enum collection accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @param parts The part of these enum declarations. It will indicate the
* namespace where find given enum collection.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog,
CommonHelper.CKParts parts) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct GeneralReflection { const char* mName; };");
indent.puts("// template<typename _Ty>");
indent.puts("// using GeneralReflectionArray = std::vector<std::pair<_Ty, GeneralReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
// write declarations
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
indent.printf("extern const GeneralReflectionArray<LibCmo::%s::%s> %s;",
CommonHelper.getCKPartsNamespace(parts), enum_t.mEnumName, enum_t.mEnumName);
}
indent.puts("");
indent.puts("");
indent.puts("");
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("const GeneralReflectionArray<LibCmo::%s::%s> %s {", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ LibCmo::%s::%s::%s, {\"%s\"} },", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
/**
* Write an enum collection accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum collection accessible value
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @param parts The part of these enum declarations.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog, CommonHelper.CKParts parts)
throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog, parts);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum collection accessible value
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @param parts The part of these enum declarations.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
// create a enum collection to fulfill the requirement of internal writer.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col, parts);
fs.close();
}
// =========== Specialized C++ Enum Accessible Value Writer ===========
// Only accessible value part of CERROR and CK_CLASSID need to be specialized.
// The enum self do not need special treat. Just write them normally.
/**
* Specialized CKERROR accessible value writer.
* <p>
* The declaration of CKERROR do not need special treat. It is okey to use
* common writer.
*
* @param filename The name of written file.
* @param errors The {@linkplain EnumsHelper.Enum_t} instance storing CKERROR.
* @throws Exception
*/
public static void writeCkErrorAccVal(String filename, EnumsHelper.Enum_t errors) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct CkErrorReflection { const char* mName; const char* mDescription; };");
indent.puts("// using CkErrorReflectionArray = std::vector<std::pair<LibCmo::CK2::CKERROR, CkErrorReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
// write implementation
indent.puts("const CkErrorReflectionArray CKERROR {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : errors.mEntries) {
String comment = CommonHelper.escapeString(entry.mEntryComment);
if (comment == null)
comment = "";
indent.printf("{ LibCmo::CK2::CKERROR::%s, { \"%s\", \"%s\" } },", entry.mEntryName, entry.mEntryName,
comment);
}
indent.dec();
indent.puts("};");
writer.close();
}
/**
* Specialized CK_CLASSID accessible value writer.
* <p>
* The declaration of CK_CLASSID do not need special treat. It is okey to use
* common writer.
*
* @param filename The name of written file.
* @param classids The {@linkplain EnumsHelper.Enum_t} instance storing
* CK_CLASSID.
* @throws Exception
*/
public static void writeCkClassidAccVal(String filename, EnumsHelper.Enum_t classids) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Cpp);
// write type defination (just to let user know what the type is)
indent.puts("// struct CkClassidReflection { std::vector<const char*> mHierarchy; };");
indent.puts("// using CkClassidReflectionArray = std::vector<std::pair<LibCmo::CK2::CK_CLASSID, CkClassidReflection>>;");
indent.puts("");
indent.puts("");
indent.puts("");
indent.puts("const CkClassidReflectionArray CK_CLASSID {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : classids.mEntries) {
EnumsHelper.EnumEntryWithHierarchy_t specialized = (EnumsHelper.EnumEntryWithHierarchy_t) entry;
String hierarchy = specialized.mHierarchy.stream().map(value -> value.mEntryName)
.collect(Collectors.joining("\", \""));
indent.printf("{ LibCmo::CK2::CK_CLASSID::%s, { { \"%s\" } } },", entry.mEntryName, hierarchy);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -1,26 +0,0 @@
import java.io.OutputStreamWriter;
/**
* The nameof values writer for CKERROR
*/
public class ErrorsWriter {
public static void writeAccVal(String filename, EnumsHelper.Enum_t errors) throws Exception {
OutputStreamWriter writer = CommonHelper.openOutputFile(filename);
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
indent.puts("const CkErrorReflectionArray CKERROR {");
indent.inc();
for (EnumsHelper.EnumEntry_t entry : errors.mEntries) {
String comment = CommonHelper.escapeString(entry.mEntryComment);
if (comment == null)
comment = "";
indent.printf("{ LibCmo::CK2::CKERROR::%s, { \"%s\", \"%s\" } },", entry.mEntryName, entry.mEntryName,
comment);
}
indent.dec();
indent.puts("};");
writer.close();
}
}

View File

@ -1,212 +0,0 @@
import java.io.OutputStreamWriter;
import java.util.Locale;
/**
* Generic Enum Writer. Including Data Type Defination and Nameof Values.
*/
public class GeneralWriter {
public static void writeEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum start
indent.printf("enum class %s : %s {", enum_t.mEnumName,
CommonHelper.getEnumUnderlyingType(enum_t.mCanUnsigned));
indent.inc();
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s,", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s,", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeEnums(fs, prog);
fs.close();
}
public static void writeEnum(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writeEnums(writer, col);
}
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeEnum(fs, _enum);
fs.close();
}
public static void writeAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog,
CommonHelper.CKParts parts) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.CPP);
// write decls
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
indent.printf("extern const GeneralReflectionArray<LibCmo::%s::%s> %s;",
CommonHelper.getCKPartsNamespace(parts), enum_t.mEnumName, enum_t.mEnumName);
}
indent.puts("");
indent.puts("");
indent.puts("");
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("const GeneralReflectionArray<LibCmo::%s::%s> %s {", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
indent.printf("{ LibCmo::%s::%s::%s, {\"%s\"} },", CommonHelper.getCKPartsNamespace(parts),
enum_t.mEnumName, enumEntry_t.mEntryName, enumEntry_t.mEntryName);
}
// write enum tail
indent.dec();
indent.puts("};");
}
}
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog, CommonHelper.CKParts parts)
throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeAccVals(fs, prog, parts);
fs.close();
}
public static void writeAccVal(OutputStreamWriter writer, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writeAccVals(writer, col, parts);
}
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum, CommonHelper.CKParts parts)
throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writeAccVal(fs, _enum, parts);
fs.close();
}
public static void writePyEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum start
indent.printf("class %s(enum.IntEnum):", enum_t.mEnumName);
indent.inc();
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s = auto()", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s", enumEntry_t.mEntryName,
CommonHelper.convertToPythonNumber(enumEntry_t.mEntryValue));
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// enum tail
indent.dec();
}
}
public static void writePyEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyEnums(fs, prog);
fs.close();
}
public static void writePyEnum(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writePyEnums(writer, col);
}
public static void writePyEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyEnum(fs, _enum);
fs.close();
}
private static String extractHumanReadableEntryName(String entry_name) {
// remove first part (any content before underline '_')
entry_name = entry_name.replaceFirst("^[a-zA-Z0-9]+_", "");
// lower all chars except first char
if (entry_name.length() < 1)
return entry_name;
else
return entry_name.substring(0, 1) + entry_name.substring(1).toLowerCase(Locale.ROOT);
}
public static void writePyAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog) throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("g_Annotation_%s: dict[int, EnumAnnotation] = {", enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
String comment = "";
if (enumEntry_t.mEntryComment != null) {
comment = CommonHelper.escapeString(enumEntry_t.mEntryComment);
}
indent.printf("%s.%s.value: EnumAnnotation(\"%s\", \"%s\"),", enum_t.mEnumName, enumEntry_t.mEntryName,
extractHumanReadableEntryName(enumEntry_t.mEntryName), comment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
public static void writePyAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyAccVals(fs, prog);
fs.close();
}
public static void writePyAccVal(OutputStreamWriter writer, EnumsHelper.Enum_t _enum) throws Exception {
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
writePyAccVals(writer, col);
}
public static void writePyAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
writePyAccVal(fs, _enum);
fs.close();
}
}

View File

@ -8,7 +8,8 @@ public class IndentHelper {
// set indent chars
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
mIndentChars = CommonHelper.getIndentString(true);
break;
case Python:
@ -67,7 +68,8 @@ public class IndentHelper {
return;
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
puts("/**");
mWriter.write(System.lineSeparator());
@ -100,7 +102,8 @@ public class IndentHelper {
mWriter.write(mIndentChars);
switch (mLangType) {
case CPP:
case Cpp:
case CSharp:
mWriter.write(String.format("/**< %s */", CommonHelper.removeEol(comment)));
break;
case Python:

View File

@ -1,10 +1,21 @@
import java.io.OutputStreamWriter;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class MainRunner {
/**
* Extract an enums collection from given file.
* <p>
* This function is the most commonly used function for extracting enums.
* <p>
* This function is used for a file which only contain enum declarations. This
* is not suit for extracting CKERROR and CK_CLASSID. For these declarations,
* please use their specialized extractor as described following.
*
* @param infile The file for reading.
* @return An {@linkplain EnumsHelper.EnumCollection_t} instance.
* @throws Exception
*/
private static EnumsHelper.EnumCollection_t getEnumsCollection(String infile) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -20,6 +31,21 @@ public class MainRunner {
return worker.getEnums();
}
/**
* Extract a series of "#define" syntax as an enum.
* <p>
* This function will assume that given file only contain C++ "#define" syntax.
* After reading it, it will re-organize it as an enum and return. This only is
* used by CKERROR now. But it suit for more scenarios if there are something
* like CKERROR in future.
*
* @param infile The file for reading.
* @param assignedEnumName The desired name of organized enum instance.
* Contemporary this field should always be "CKERROR"
* because no one else is using it.
* @return An {@linkplain EnumsHelper.Enum_t} instance.
* @throws Exception
*/
private static EnumsHelper.Enum_t organiseDefines(String infile, String assignedEnumName) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -38,6 +64,22 @@ public class MainRunner {
return result;
}
/**
* Extract a series of macro define as an enum, considering its indent to build
* hierarchy.
* <p>
* This is specialized enum extractor of CK_CLASSID. The given file should use a
* series "#define" syntax to describe enum, and use Tab as the indent before
* each "#define" syntax to indicate its hierarchy.
*
* @param infile The file for reading.
* @return An {@linkplain EnumsHelper.Enum_t} instance. Actually it is an
* instance to {@linkplain EnumsHelper.Enum_t} whose entries is
* {@linkplain EnumsHelper.EnumEntryWithHierarchy_t}, the child class of
* {@linkplain EnumsHelper.EnumEntry_t} (the entry type of common
* {@linkplain EnumsHelper.Enum_t}) with extra hierarchy infos.
* @throws Exception
*/
private static EnumsHelper.Enum_t organiseClassid(String infile) throws Exception {
CommonHelper.InputFilePair pair = CommonHelper.openInputFile(infile);
CKGeneralLexer lexer = new CKGeneralLexer(pair.mAntlrStream);
@ -59,57 +101,74 @@ public class MainRunner {
public static void main(String[] args) throws Exception {
// =========== CKERROR ===========
EnumsHelper.Enum_t ckerror = organiseDefines("src/CKError.txt", "CKERROR");
GeneralWriter.writeEnum("dest/CKError.hpp", ckerror);
GeneralWriter.writePyEnum("dest/CKError.py", ckerror);
ErrorsWriter.writeAccVal("dest/CKError.AccVal.hpp", ckerror);
GeneralWriter.writePyAccVal("dest/CKError.AccVal.py", ckerror);
EnumsHelper.Enum_t ckerror = organiseDefines("src/CKERROR.txt", "CKERROR");
CppWriter.writeEnum("dest/CKERROR.hpp", ckerror);
PythonWriter.writeEnum("dest/CKERROR.py", ckerror);
CSharpWriter.writeEnum("dest/CKERROR.cs", ckerror);
CppWriter.writeCkErrorAccVal("dest/CKERROR.AccVal.hpp", ckerror);
PythonWriter.writeAccVal("dest/CKERROR.AccVal.py", ckerror);
CSharpWriter.writeAccVal("dest/CKERROR.AccVal.cs", ckerror);
// =========== CK_CLASSID ===========
EnumsHelper.Enum_t classid = organiseClassid("src/CK_CLASSID.txt");
GeneralWriter.writeEnum("dest/CK_CLASSID.hpp", classid);
GeneralWriter.writePyEnum("dest/CK_CLASSID.py", classid);
ClassidWriter.writeAccVal("dest/CK_CLASSID.AccVal.hpp", classid);
GeneralWriter.writePyAccVal("dest/CK_CLASSID.AccVal.py", classid);
CppWriter.writeEnum("dest/CK_CLASSID.hpp", classid);
PythonWriter.writeEnum("dest/CK_CLASSID.py", classid);
CSharpWriter.writeEnum("dest/CK_CLASSID.cs", classid);
CppWriter.writeCkClassidAccVal("dest/CK_CLASSID.AccVal.hpp", classid);
PythonWriter.writeAccVal("dest/CK_CLASSID.AccVal.py", classid);
// =========== Define2 ===========
// Define2 do not need values.
// Define2 do not need annotation output.
// Because they are CKStateChunk used value which are not exposed to outside.
EnumsHelper.EnumCollection_t def2 = getEnumsCollection("src/Defines2.txt");
GeneralWriter.writeEnums("dest/CK_CLASSID.hpp", def2);
GeneralWriter.writePyEnums("dest/CK_CLASSID.py", def2);
CppWriter.writeEnums("dest/Defines2.hpp", def2);
PythonWriter.writeEnums("dest/Defines2.py", def2);
CSharpWriter.writeEnums("dest/Defines2.cs", def2);
// =========== Combined enums ===========
EnumsHelper.EnumCollection_t ck2Enums = getEnumsCollection("src/CKEnums.txt"),
vxEnums = getEnumsCollection("src/VxEnums.txt");
GeneralWriter.writeEnums("dest/CKEnums.hpp", ck2Enums);
GeneralWriter.writePyEnums("dest/CKEnums.py", ck2Enums);
GeneralWriter.writeAccVals("dest/CKEnums.AccVal.hpp", ck2Enums, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVals("dest/CKEnums.AccVal.py", ck2Enums);
GeneralWriter.writeEnums("dest/VxEnums.hpp", vxEnums);
GeneralWriter.writePyEnums("dest/VxEnums.py", vxEnums);
GeneralWriter.writeAccVals("dest/VxEnums.AccVal.hpp", vxEnums, CommonHelper.CKParts.VxMath);
GeneralWriter.writePyAccVals("dest/VxEnums.AccVal.py", vxEnums);
CppWriter.writeEnums("dest/CKEnums.hpp", ck2Enums);
PythonWriter.writeEnums("dest/CKEnums.py", ck2Enums);
CSharpWriter.writeEnums("dest/CKEnums.cs", ck2Enums);
CppWriter.writeAccVals("dest/CKEnums.AccVal.hpp", ck2Enums, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVals("dest/CKEnums.AccVal.py", ck2Enums);
CSharpWriter.writeAccVals("dest/CKEnums.AccVal.cs", ck2Enums);
CppWriter.writeEnums("dest/VxEnums.hpp", vxEnums);
PythonWriter.writeEnums("dest/VxEnums.py", vxEnums);
CSharpWriter.writeEnums("dest/VxEnums.cs", vxEnums);
CppWriter.writeAccVals("dest/VxEnums.AccVal.hpp", vxEnums, CommonHelper.CKParts.VxMath);
PythonWriter.writeAccVals("dest/VxEnums.AccVal.py", vxEnums);
CSharpWriter.writeAccVals("dest/VxEnums.AccVal.cs", vxEnums);
// =========== Single enums ===========
EnumsHelper.Enum_t single;
single = organiseDefines("src/CK_STATECHUNK_CHUNKVERSION.txt", "CK_STATECHUNK_CHUNKVERSION");
GeneralWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.hpp", single);
GeneralWriter.writePyEnum("dest/CK_STATECHUNK_CHUNKVERSION.py", single);
GeneralWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.py", single);
CppWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.hpp", single);
PythonWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.py", single);
CSharpWriter.writeEnum("dest/CK_STATECHUNK_CHUNKVERSION.cs", single);
CppWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_STATECHUNK_CHUNKVERSION.AccVal.cs", single);
single = organiseDefines("src/CK_STATECHUNK_DATAVERSION.txt", "CK_STATECHUNK_DATAVERSION");
GeneralWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.hpp", single);
GeneralWriter.writePyEnum("dest/CK_STATECHUNK_DATAVERSION.py", single);
GeneralWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.py", single);
CppWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.hpp", single);
PythonWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.py", single);
CSharpWriter.writeEnum("dest/CK_STATECHUNK_DATAVERSION.cs", single);
CppWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_STATECHUNK_DATAVERSION.AccVal.cs", single);
single = organiseDefines("src/CK_BITMAPDATA_FLAGS.txt", "CK_BITMAPDATA_FLAGS");
GeneralWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.hpp", single);
GeneralWriter.writePyEnum("dest/CK_BITMAPDATA_FLAGS.py", single);
GeneralWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.hpp", single, CommonHelper.CKParts.CK2);
GeneralWriter.writePyAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.py", single);
CppWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.hpp", single);
PythonWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.py", single);
CSharpWriter.writeEnum("dest/CK_BITMAPDATA_FLAGS.cs", single);
CppWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.hpp", single, CommonHelper.CKParts.CK2);
PythonWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.py", single);
CSharpWriter.writeAccVal("dest/CK_BITMAPDATA_FLAGS.AccVal.cs", single);
// print message.
System.out.println("DONE!");

View File

@ -0,0 +1,185 @@
import java.io.OutputStreamWriter;
import java.util.Locale;
/**
* Write enum declarations and accessible value into Python format.
*/
public class PythonWriter {
// =========== Python Enum Declaration Writer ===========
/**
* Internal real enum declaration writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteEnums(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum start
indent.printf("class %s(enum.IntEnum):", enum_t.mEnumName);
indent.inc();
// write enum comment
indent.briefComment(enum_t.mEnumComment);
// write enum entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
// write entry self
if (enumEntry_t.mEntryValue == null) {
indent.printf("%s = auto()", enumEntry_t.mEntryName);
} else {
indent.printf("%s = %s", enumEntry_t.mEntryName,
CommonHelper.convertToPythonNumber(enumEntry_t.mEntryValue));
}
// write entry comment after member
indent.afterMemberComment(enumEntry_t.mEntryComment);
}
// enum tail
indent.dec();
}
}
/**
* Write an enum declaration collection into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeEnums(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, prog);
fs.close();
}
/**
* Write a single enum declaration into given file.
* <p>
* Actually this is a wrapper of internal enum declaration collection writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeEnum(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create collection from single enum
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteEnums(fs, col);
fs.close();
}
// =========== Python Enum Accessible Value Writer ===========
/**
* Try generate human readable name from enum entry name.
* <p>
* This function is only served for Python code generation.
* <p>
* As you noticed, almost entries of CK enums are fully capital and splitted by
* underline. This is really not good for human reading, especially those who
* are not programmer. So this function will try give these programmer-oriented
* entry name a human readable name as its display name. However, this extract
* method is not perfect. It simply do some split and replacement so the
* generated content may still not good for reader.
*
* @param entry_name The name of enum entry
* @return A human readable entry name. No guaranteen that return value is must
* human readable.
*/
private static String extractHumanReadableEntryName(String entry_name) {
// remove first part (any content before underline '_')
entry_name = entry_name.replaceFirst("^[a-zA-Z0-9]+_", "");
// lower all chars except first char
if (entry_name.length() < 1)
return entry_name;
else
return entry_name.substring(0, 1) + entry_name.substring(1).toLowerCase(Locale.ROOT);
}
/**
* Internal real enum accessible value writer.
*
* @param writer {@linkplain java.io.OutputStreamWriter} instance for writing.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for writing.
* @throws Exception
*/
private static void internalWriteAccVals(OutputStreamWriter writer, EnumsHelper.EnumCollection_t prog)
throws Exception {
IndentHelper indent = new IndentHelper(writer, CommonHelper.LangType.Python);
// write implements
for (EnumsHelper.Enum_t enum_t : prog.mEnums) {
// write enum desc header
indent.printf("g_Annotation_%s: dict[int, EnumAnnotation] = {", enum_t.mEnumName);
indent.inc();
// write enum desc entries
for (EnumsHelper.EnumEntry_t enumEntry_t : enum_t.mEntries) {
String comment = "";
if (enumEntry_t.mEntryComment != null) {
comment = CommonHelper.escapeString(enumEntry_t.mEntryComment);
}
indent.printf("%s.%s.value: EnumAnnotation(\"%s\", \"%s\"),", enum_t.mEnumName, enumEntry_t.mEntryName,
extractHumanReadableEntryName(enumEntry_t.mEntryName), comment);
}
// write enum tail
indent.dec();
indent.puts("}");
}
}
/**
* Write an enum accessible value collection into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param prog {@linkplain EnumsHelper.EnumCollection_t} instance for
* writing.
* @throws Exception
*/
public static void writeAccVals(String filename, EnumsHelper.EnumCollection_t prog) throws Exception {
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, prog);
fs.close();
}
/**
* Write a single enum accessible value into given file.
* <p>
* Actually this is a wrapper of internal enum accessible value collection
* writer.
*
* @param filename The name of written file.
* @param _enum {@linkplain EnumsHelper.Enum_t} instance for writing.
* @throws Exception
*/
public static void writeAccVal(String filename, EnumsHelper.Enum_t _enum) throws Exception {
// create a collection with single enum.
EnumsHelper.EnumCollection_t col = new EnumsHelper.EnumCollection_t();
col.mEnums.add(_enum);
// open file and write
OutputStreamWriter fs = CommonHelper.openOutputFile(filename);
internalWriteAccVals(fs, col);
fs.close();
}
}

View File

@ -1,6 +1,10 @@
# Code Gen
# Enums Migration
A helper program to generate some definations.
A helper program to migrate existing Virtools enum declarations into other formats.
Original Virtools SDK have various enum declarations. All of them are defined as C format and their formation are not uniform. This sub-project will use laxer and parser to recognize these diverse declarations, extract them as a series of uniform Java data struct and output them as C++ code (as C++ enum class syntax for LibCmo using), Python code (for PyBMap using), and C# code (for BMapSharp using).
The steps processing existing enum declaration is called migration as this sub-project name told.
```
antlr4 CKGeneralLexer.g4