write shit
This commit is contained in:
parent
c1aac0beda
commit
77d8bbf3ba
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -13,6 +13,8 @@ temp/
|
||||||
## Special Treat of CodeGen
|
## Special Treat of CodeGen
|
||||||
CodeGen.old/
|
CodeGen.old/
|
||||||
CodeGen/dest/*.txt
|
CodeGen/dest/*.txt
|
||||||
|
CodeGen/.*
|
||||||
|
CodeGen/*.class
|
||||||
|
|
||||||
CodeGen/CKGeneralLexer*.*
|
CodeGen/CKGeneralLexer*.*
|
||||||
CodeGen/CKEnumParser*.*
|
CodeGen/CKEnumParser*.*
|
||||||
|
|
76
CodeGen/CKCommonHelper.java
Normal file
76
CodeGen/CKCommonHelper.java
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
|
||||||
|
public class CKCommonHelper {
|
||||||
|
|
||||||
|
public static Token getPreChannelToken(BufferedTokenStream stream, Token token, int channel) {
|
||||||
|
List<Token> tokens = stream.getHiddenTokensToLeft(token.getTokenIndex(), channel);
|
||||||
|
if (tokens == null)
|
||||||
|
return null;
|
||||||
|
return tokens.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Token getPostChannelToken(BufferedTokenStream stream, Token token, int channel) {
|
||||||
|
List<Token> tokens = stream.getHiddenTokensToRight(token.getTokenIndex(), channel);
|
||||||
|
if (tokens == null)
|
||||||
|
return null;
|
||||||
|
return tokens.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String cutComment(Token comment) {
|
||||||
|
if (comment == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
switch (comment.getType()) {
|
||||||
|
case CKGeneralLexer.CKGENERAL_LINE_COMMENT: {
|
||||||
|
return comment.getText().substring(2);
|
||||||
|
}
|
||||||
|
case CKGeneralLexer.CKGENERAL_BLOCK_COMMENT: {
|
||||||
|
String cache = comment.getText();
|
||||||
|
return cache.substring(2, cache.length() - 4);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return comment.getText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNegtiveNumber(String numstr) {
|
||||||
|
return numstr.startsWith("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CKParts {
|
||||||
|
CK2, VxMath
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCKPartsNamespace(CKParts parts) {
|
||||||
|
switch (parts) {
|
||||||
|
case CK2:
|
||||||
|
return "CK2";
|
||||||
|
case VxMath:
|
||||||
|
return "VxMath";
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected value: " + parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getEnumUnderlayingType(boolean canUnsigned) {
|
||||||
|
return canUnsigned ? "uint32_t" : "int32_t";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OutputStreamWriter openOutputFile(String filename) throws Exception {
|
||||||
|
FileOutputStream fs = new FileOutputStream(filename);
|
||||||
|
return new OutputStreamWriter(fs, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapeString(String strl) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
CodeGen/CKEnumCommentsHelper.java
Normal file
51
CodeGen/CKEnumCommentsHelper.java
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
|
||||||
|
public class CKEnumCommentsHelper {
|
||||||
|
|
||||||
|
enum CommentsPosition {
|
||||||
|
Unknown, Precomment, Postcomment
|
||||||
|
}
|
||||||
|
|
||||||
|
public CKEnumCommentsHelper(BufferedTokenStream tokenStream) {
|
||||||
|
mTokenStream = tokenStream;
|
||||||
|
mCommentsPos = CommentsPosition.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedTokenStream mTokenStream;
|
||||||
|
private CommentsPosition mCommentsPos;
|
||||||
|
|
||||||
|
public String getComment(Token preToken, Token postToken) {
|
||||||
|
switch (mCommentsPos) {
|
||||||
|
case Unknown: {
|
||||||
|
// if we don't know where is our token,
|
||||||
|
// we should assume it is from precomment to postcomment
|
||||||
|
// and check it.
|
||||||
|
Token precomment = CKCommonHelper.getPreChannelToken(mTokenStream, preToken, CKGeneralLexer.COMMENTS);
|
||||||
|
if (precomment != null) {
|
||||||
|
mCommentsPos = CommentsPosition.Precomment;
|
||||||
|
return CKCommonHelper.cutComment(precomment);
|
||||||
|
}
|
||||||
|
|
||||||
|
Token postcomment = CKCommonHelper.getPostChannelToken(mTokenStream, postToken, CKGeneralLexer.COMMENTS);
|
||||||
|
if (postcomment != null) {
|
||||||
|
mCommentsPos = CommentsPosition.Postcomment;
|
||||||
|
return CKCommonHelper.cutComment(postcomment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// really do not have comment, return empty and keep comment pos
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case Precomment: {
|
||||||
|
Token comment = CKCommonHelper.getPreChannelToken(mTokenStream, preToken, CKGeneralLexer.COMMENTS);
|
||||||
|
return CKCommonHelper.cutComment(comment);
|
||||||
|
}
|
||||||
|
case Postcomment: {
|
||||||
|
Token comment = CKCommonHelper.getPostChannelToken(mTokenStream, postToken, CKGeneralLexer.COMMENTS);
|
||||||
|
return CKCommonHelper.cutComment(comment);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,11 +4,11 @@ options { tokenVocab = CKGeneralLexer; }
|
||||||
prog: enumBody+ ;
|
prog: enumBody+ ;
|
||||||
|
|
||||||
enumBody: CKGENERAL_TYPEDEF? CKGENERAL_ENUM CKGENERAL_ID CKGENERAL_LBRACKET
|
enumBody: CKGENERAL_TYPEDEF? CKGENERAL_ENUM CKGENERAL_ID CKGENERAL_LBRACKET
|
||||||
entryPair (CKGENERAL_COMMA entryPair)*
|
entryPair+
|
||||||
CKGENERAL_RBRACKET CKGENERAL_ID? CKGENERAL_SEMICOLON ;
|
CKGENERAL_RBRACKET CKGENERAL_ID? CKGENERAL_SEMICOLON ;
|
||||||
|
|
||||||
entryPair: CKGENERAL_ID (CKGENERAL_EQUAL entryValue)? ;
|
entryPair: CKGENERAL_ID (CKGENERAL_EQUAL entryValue)? CKGENERAL_COMMA? ;
|
||||||
|
|
||||||
entryValue: CKGENERAL_NUM (CKGENERAL_LSHIFT CKGENERAL_NUM)* # entryDirectValue
|
entryValue: CKGENERAL_NUM (CKGENERAL_LSHIFT CKGENERAL_NUM)? # entryDirectValue
|
||||||
| CKGENERAL_ID (CKGENERAL_OR CKGENERAL_ID)* # entryRelativeValue
|
| CKGENERAL_ID (CKGENERAL_OR CKGENERAL_ID)* # entryRelativeValue
|
||||||
;
|
;
|
192
CodeGen/CKEnumRunner.java
Normal file
192
CodeGen/CKEnumRunner.java
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import org.antlr.v4.runtime.tree.*;
|
||||||
|
|
||||||
|
public class CKEnumRunner {
|
||||||
|
public static class EnumEntry_t {
|
||||||
|
public EnumEntry_t() {
|
||||||
|
mEntryName = null;
|
||||||
|
mEntryValue = null;
|
||||||
|
mEntryComment = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String mEntryName;
|
||||||
|
public String mEntryValue; // setting to null mean this entry do not have specified value.
|
||||||
|
public String mEntryComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Enum_t {
|
||||||
|
public Enum_t() {
|
||||||
|
mEnumName = null;
|
||||||
|
mEnumComment = null;
|
||||||
|
mCanUnsigned = true;
|
||||||
|
mEntries = new Vector<EnumEntry_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String mEnumName;
|
||||||
|
public String mEnumComment;
|
||||||
|
public boolean mCanUnsigned;
|
||||||
|
public Vector<EnumEntry_t> mEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EnumWalker extends CKEnumParserBaseListener {
|
||||||
|
public EnumWalker(BufferedTokenStream tokenStream) {
|
||||||
|
mTokenStream = tokenStream;
|
||||||
|
mCommentsHelper = new CKEnumCommentsHelper(tokenStream);
|
||||||
|
mResult = null;
|
||||||
|
|
||||||
|
mCurrentProg = null;
|
||||||
|
mCurrentEnum = null;
|
||||||
|
mCurrentEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Enum_t> getResult() {
|
||||||
|
return mResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedTokenStream mTokenStream;
|
||||||
|
private CKEnumCommentsHelper mCommentsHelper;
|
||||||
|
private Vector<Enum_t> mResult;
|
||||||
|
|
||||||
|
private Vector<Enum_t> mCurrentProg;
|
||||||
|
private Enum_t mCurrentEnum;
|
||||||
|
private EnumEntry_t mCurrentEntry;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterProg(CKEnumParser.ProgContext ctx) {
|
||||||
|
mCurrentProg = new Vector<Enum_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitProg(CKEnumParser.ProgContext ctx) {
|
||||||
|
mResult = mCurrentProg;
|
||||||
|
mCurrentProg = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterEnumBody(CKEnumParser.EnumBodyContext ctx) {
|
||||||
|
mCurrentEnum = new Enum_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitEnumBody(CKEnumParser.EnumBodyContext ctx) {
|
||||||
|
// get enum comment
|
||||||
|
mCurrentEnum.mEnumComment = CKCommonHelper.cutComment(
|
||||||
|
CKCommonHelper.getPreChannelToken(mTokenStream, ctx.getStart(), CKGeneralLexer.COMMENTS));
|
||||||
|
// get the last name (for typedef case)
|
||||||
|
List<TerminalNode> allNames = ctx.CKGENERAL_ID();
|
||||||
|
mCurrentEnum.mEnumName = allNames.get(allNames.size() - 1).getText();
|
||||||
|
|
||||||
|
mCurrentProg.add(mCurrentEnum);
|
||||||
|
mCurrentEnum = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enterEntryPair(CKEnumParser.EntryPairContext ctx) {
|
||||||
|
mCurrentEntry = new EnumEntry_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitEntryPair(CKEnumParser.EntryPairContext ctx) {
|
||||||
|
// get entry comment
|
||||||
|
mCurrentEntry.mEntryComment = mCommentsHelper.getComment(ctx.getStart(), ctx.getStop());
|
||||||
|
// get entry name
|
||||||
|
mCurrentEntry.mEntryName = ctx.CKGENERAL_ID().getText();
|
||||||
|
|
||||||
|
mCurrentEnum.mEntries.add(mCurrentEntry);
|
||||||
|
mCurrentEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitEntryDirectValue(CKEnumParser.EntryDirectValueContext ctx) {
|
||||||
|
// get all numbers
|
||||||
|
List<TerminalNode> nums = ctx.CKGENERAL_NUM();
|
||||||
|
|
||||||
|
switch (nums.size()) {
|
||||||
|
case 1: {
|
||||||
|
TerminalNode node = nums.get(0);
|
||||||
|
// check whether target is minus number
|
||||||
|
if (CKCommonHelper.isNegtiveNumber(node.getText())) {
|
||||||
|
mCurrentEnum.mCanUnsigned = false;
|
||||||
|
}
|
||||||
|
// set value
|
||||||
|
mCurrentEntry.mEntryValue = node.getText();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
TerminalNode num = nums.get(0), offset = nums.get(1);
|
||||||
|
// set value
|
||||||
|
mCurrentEntry.mEntryValue = String.format("{} << {}", num.getText(), offset.getText());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected value: " + nums.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exitEntryRelativeValue(CKEnumParser.EntryRelativeValueContext ctx) {
|
||||||
|
// get all identifiers and join them
|
||||||
|
mCurrentEntry.mEntryValue = String.join(" | ",
|
||||||
|
ctx.CKGENERAL_ID().stream().map(value -> value.getText()).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EnumProgWriter {
|
||||||
|
public static void writeEnums(OutputStreamWriter writer, CKCommonHelper.CKParts parts, List<Enum_t> prog)
|
||||||
|
throws Exception {
|
||||||
|
CKIndentHelper indent = new CKIndentHelper(writer);
|
||||||
|
indent.puts("#pragma once");
|
||||||
|
indent.puts("#include <cstdint>");
|
||||||
|
indent.printf("namespace LibCmo::{} {{", CKCommonHelper.getCKPartsNamespace(parts));
|
||||||
|
indent.inc();
|
||||||
|
|
||||||
|
// write enums
|
||||||
|
for (Enum_t enum_t : prog) {
|
||||||
|
// write enum comment
|
||||||
|
indent.briefComment(enum_t.mEnumComment);
|
||||||
|
|
||||||
|
// write enum start
|
||||||
|
indent.printf("enum class {} : {} {{", enum_t.mEnumName,
|
||||||
|
CKCommonHelper.getEnumUnderlayingType(enum_t.mCanUnsigned));
|
||||||
|
indent.inc();
|
||||||
|
|
||||||
|
// write enum entries
|
||||||
|
for (EnumEntry_t enumEntry_t : enum_t.mEntries) {
|
||||||
|
// write entry self
|
||||||
|
if (enumEntry_t.mEntryValue == null) {
|
||||||
|
indent.printf("{},", enumEntry_t.mEntryName);
|
||||||
|
} else {
|
||||||
|
indent.printf("{} = {},", enumEntry_t.mEntryName, enumEntry_t.mEntryValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write entry comment after member
|
||||||
|
indent.afterMemberComment(enumEntry_t.mEntryComment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write enum tail
|
||||||
|
indent.dec();
|
||||||
|
indent.puts("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
indent.dec();
|
||||||
|
indent.puts("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeComments(OutputStreamWriter writer, List<Enum_t> prog) throws Exception {
|
||||||
|
CKIndentHelper indent = new CKIndentHelper(writer);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(String infilename, String outfilename) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ CKGENERAL_COMMA: ',' ;
|
||||||
|
|
||||||
// identifider and number
|
// identifider and number
|
||||||
CKGENERAL_ID: [_a-zA-Z][_a-zA-Z0-9]* ;
|
CKGENERAL_ID: [_a-zA-Z][_a-zA-Z0-9]* ;
|
||||||
CKGENERAL_NUM: '-'? ('0' [xX])? [0-9a-fA-F]+ [uUlL]* ;
|
CKGENERAL_NUM: (('0'[xX]) | '-')? [0-9a-fA-F]+ [uUlL]* ;
|
||||||
|
|
||||||
// comments
|
// comments
|
||||||
CKGENERAL_LINE_COMMENT: '//' ~[\r\n]* -> channel(COMMENTS);
|
CKGENERAL_LINE_COMMENT: '//' ~[\r\n]* -> channel(COMMENTS);
|
||||||
|
|
47
CodeGen/CKIndentHelper.java
Normal file
47
CodeGen/CKIndentHelper.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
|
||||||
|
public class CKIndentHelper {
|
||||||
|
public CKIndentHelper(OutputStreamWriter writer) {
|
||||||
|
mIndent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int mIndent;
|
||||||
|
private OutputStreamWriter mWriter;
|
||||||
|
|
||||||
|
public void inc() {
|
||||||
|
++mIndent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dec() {
|
||||||
|
--mIndent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void indent() throws Exception {
|
||||||
|
mWriter.write("\n");
|
||||||
|
for (int i = 0; i < mIndent; ++i) {
|
||||||
|
mWriter.write("\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void puts(String data) throws Exception {
|
||||||
|
indent();
|
||||||
|
mWriter.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printf(String fmt, Object... args) throws Exception {
|
||||||
|
indent();
|
||||||
|
mWriter.write(String.format(fmt, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void briefComment(String fmt) throws Exception {
|
||||||
|
if (fmt == null) return;
|
||||||
|
printf("/**< {} */", fmt.replaceAll("[\\r\\n]+", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterMemberComment(String fmt) throws Exception {
|
||||||
|
if (fmt == null) return;
|
||||||
|
mWriter.write("\t");
|
||||||
|
mWriter.write(fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
CodeGen/src/VXENUMS.txt
Normal file
0
CodeGen/src/VXENUMS.txt
Normal file
Loading…
Reference in New Issue
Block a user