import java.util.Stack; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.*; /** * The specialized walker for collecting CK_CLASSID and its inherit * relationship. */ public class ClassidWalker extends CKDefinesParserBaseListener { public ClassidWalker(BufferedTokenStream tokenStream) { mTokenStream = tokenStream; mResult = null; mLevelStack = null; mCurrentEnum = null; mCurrentEntry = null; } public EnumsHelper.Enum_t getEnum() { return mResult; } private int getClassidLevel(Token defineHead) { Token ws = CommonHelper.getPreChannelToken(mTokenStream, defineHead, CKGeneralLexer.WHITESPACE); if (ws == null) return 0; // reverse finding how many tab used. int counter = 0; char[] wstxt = ws.getText().toCharArray(); for (int i = wstxt.length - 1; i >= 0; i--) { if (wstxt[i] == '\t') { counter++; } else { break; } } return counter; } private void safePop() { if (mLevelStack.size() != 0) mLevelStack.pop(); } private void safePopTimes(int times) { for (int i = 0; i < times; i++) { if (mLevelStack.size() != 0) mLevelStack.pop(); } } private BufferedTokenStream mTokenStream; private EnumsHelper.Enum_t mResult; private int mLevel; private Stack mLevelStack; private EnumsHelper.Enum_t mCurrentEnum; private EnumsHelper.EnumEntryWithHierarchy_t mCurrentEntry; @Override public void enterProg(CKDefinesParser.ProgContext ctx) { mLevel = 0; mLevelStack = new Stack(); mCurrentEnum = new EnumsHelper.Enum_t(); } @Override public void exitProg(CKDefinesParser.ProgContext ctx) { mLevel = 0; mLevelStack = null; // classid is signed int and do not have flags feature. mCurrentEnum.mCanUnsigned = false; mCurrentEnum.mUseFlags = false; mResult = mCurrentEnum; mCurrentEnum = null; } @Override public void enterDefinePair(CKDefinesParser.DefinePairContext ctx) { mCurrentEntry = new EnumsHelper.EnumEntryWithHierarchy_t(); } @Override public void exitDefinePair(CKDefinesParser.DefinePairContext ctx) { // fill entry info mCurrentEntry.mEntryName = ctx.CKGENERAL_ID(0).getText(); mCurrentEntry.mEntryValue = ctx.CKGENERAL_NUM().getText(); // fill entry level info int this_level = getClassidLevel(ctx.getStart()); if (this_level > mLevel) { // level up mLevel++; mLevelStack.push(mCurrentEntry); mCurrentEntry.mHierarchy.addAll(mLevelStack); } else if (this_level == mLevel) { safePop(); mLevelStack.push(mCurrentEntry); mCurrentEntry.mHierarchy.addAll(mLevelStack); } else if (this_level < mLevel) { // level down safePopTimes(mLevel - this_level + 1); mLevel = this_level; mLevelStack.push(mCurrentEntry); mCurrentEntry.mHierarchy.addAll(mLevelStack); } // move to list mCurrentEnum.mEntries.add(mCurrentEntry); mCurrentEntry = null; } }