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(); } public String mEnumName; public String mEnumComment; public boolean mCanUnsigned; public Vector 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 getResult() { return mResult; } private BufferedTokenStream mTokenStream; private CKEnumCommentsHelper mCommentsHelper; private Vector mResult; private Vector mCurrentProg; private Enum_t mCurrentEnum; private EnumEntry_t mCurrentEntry; @Override public void enterProg(CKEnumParser.ProgContext ctx) { mCurrentProg = new Vector(); } @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 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 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 prog) throws Exception { CKIndentHelper indent = new CKIndentHelper(writer); indent.puts("#pragma once"); indent.puts("#include "); 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 prog) throws Exception { CKIndentHelper indent = new CKIndentHelper(writer); } } public static void Run(String infilename, String outfilename) { } }