Java tutorial
package com.makkajai; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.makkajai.Constants.*; /** * ObjCToCppTranslator - The purpose of this class is to parse the Objective C file input and translate it to Cpp! * (c) 2015 Makkajai * @author Deep Shah * This code is licensed under MIT license (see LICENSE.txt for details) */ public class ObjCToCppTranslator extends ObjCBaseVisitor<Void> { private static final Dictionary<String, String> KEYWORDS_VS_TRANSLATIONS = new Hashtable<String, String>(); private static final Dictionary<String, String> TYPES_VS_TRANSLATIONS = new Hashtable<String, String>(); private static final Dictionary<String, String> METHODS_VS_TRANSLATIONS = new Hashtable<String, String>(); private static final List<String> instanceVariables; private static final List<String> methodSignatures; private static String className; private static String superClassName; private static String categoryClassName; private String fileName; private CommonTokenStream tokens; private StringBuilder outputBuffer; private boolean isProcessingInstanceMethod; private Dictionary<String, String> sourceVsDestinationText; private boolean isProtocol; static { KEYWORDS_VS_TRANSLATIONS.put(Keywords.SUPER, Keywords.BASE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SELF, Keywords.THIS); KEYWORDS_VS_TRANSLATIONS.put(Keywords.NIL, Keywords.NULL); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_PUBLIC, Keywords.PUBLIC); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_PROTECTED, Keywords.PROTECTED); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_PRIVATE, Keywords.PRIVATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.YES, Keywords.TRUE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.NO, Keywords.FALSE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_QUOTE, Keywords.QUOTE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.PERCENTAGE_QUOTE, Keywords.PERCENTAGE_S); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_CLASS, Keywords.CLASS); KEYWORDS_VS_TRANSLATIONS.put(Keywords.AT_PROTOCOL, Keywords.CLASS); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SEQUENCE_ACTIONS, Keywords.SEQUENCE_CREATEWITHVARIABLELIST); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONFINITETIME, Keywords.FINITETIMEACTION); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONMOVETO_CREATEPOSITION, Keywords.MOVETO_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONREPEATFOREVER_ACTIONWITHACTION, Keywords.REPEATFOREVER_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONSCALETO_CREATESCALE, Keywords.SCALETO_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONFADETO_CREATEOPACITY, Keywords.MAKKAJAIFADETO_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONFADEIN_CREATEOPACITY, Keywords.MAKKAJAIFADEIN_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONFADEOUT_CREATEOPACITY, Keywords.MAKKAJAIFADEOUT_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ISEQUALTOSTRING, Keywords.ISEQUAL); KEYWORDS_VS_TRANSLATIONS.put(Keywords.UP_FLOAT, Keywords.FLOAT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONSPAWN_ACTIONS, Keywords.SPAWN_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONROTATEBY_CREATEANGLE, Keywords.ROTATEBY_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONSCALEBY_CREATESCALE, Keywords.SCALEBY_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SPRITE_SPRITEWITHIMAGENAMED, Keywords.SPRITE_CREATEWITHSPRITEFRAMENAME); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SPRITE_SPRITEWITHFILE, Keywords.SPRITE_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ACTIONEASEBOUNCEOUT_ACTIONWITHACTION, Keywords.EASEBOUNCEOUT_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SZWIN_GETWIDTH, Keywords.SZWIN_WIDTH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SZWIN_GETHEIGHT, Keywords.SZWIN_HEIGHT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETSZWIN_GETWIDTH, Keywords.GETSZWIN_WIDTH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETSZWIN_GETHEIGHT, Keywords.GETSZWIN_HEIGHT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETCONTENTSIZE_GETWIDTH, Keywords.GETCONTENTSIZE_WIDTH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETCONTENTSIZE_GETHEIGHT, Keywords.GETCONTENTSIZE_HEIGHT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.CONST_STD_STRING_POINTER, Keywords.CONST_STD_STRING); KEYWORDS_VS_TRANSLATIONS.put(Keywords.CGPOINTZERO, Keywords.VEC2_ZERO); KEYWORDS_VS_TRANSLATIONS.put(Keywords.BUTTON, Keywords.UI_BUTTON); KEYWORDS_VS_TRANSLATIONS.put(Keywords.ARRAY_WITH, Keywords.CREATE_WITH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.DICTIONARY_WITH, Keywords.CREATE_WITH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.STRING_WITH, Keywords.CREATE_WITH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.DDLOGVERBOSE, Keywords.CCLOGINFO); KEYWORDS_VS_TRANSLATIONS.put(Keywords.DDLOGWARN, Keywords.CCLOGWARN); KEYWORDS_VS_TRANSLATIONS.put(Keywords.DDLOGERROR, Keywords.CCLOGERROR); KEYWORDS_VS_TRANSLATIONS.put(Keywords.TOBEDELETED_TEMP_STRING, Keywords.EMPTY); KEYWORDS_VS_TRANSLATIONS.put(Keywords.__ARRAY_ARRAY, Keywords.__ARRAY_CREATE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.DIRECTOR_SHARED_DIRECTOR, Keywords.DIRECTOR_GETINSTANCE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.CCBUTTON, Keywords.UI_BUTTON); KEYWORDS_VS_TRANSLATIONS.put(Keywords.UBYTE, Keywords.GLUBYTE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.TIME, Keywords.FLOAT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETX, Keywords.X); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETY, Keywords.Y); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETWIDTH, Keywords.WIDTH); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETHEIGHT, Keywords.HEIGHT); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETSIZE, Keywords.SIZE); KEYWORDS_VS_TRANSLATIONS.put(Keywords.GETORIGIN, Keywords.ORIGIN); KEYWORDS_VS_TRANSLATIONS.put(Keywords.CGPOINTMAKE, Keywords.VEC2); KEYWORDS_VS_TRANSLATIONS.put(Types.NS_STRING, Types.STRING); KEYWORDS_VS_TRANSLATIONS.put(Methods.CCP, Methods.VEC2); KEYWORDS_VS_TRANSLATIONS.put(Methods.CG_RECT_MAKE, Methods.RECT); KEYWORDS_VS_TRANSLATIONS.put(Methods.CG_SIZE_MAKE, Methods.SIZE); KEYWORDS_VS_TRANSLATIONS.put(Methods.ACTIONONETWO, Methods.CREATEWITHTWOACTIONS); TYPES_VS_TRANSLATIONS.put(Types.NS_OBJECT, Types.REF); TYPES_VS_TRANSLATIONS.put(Types.NS_STRING, Types.STRING); TYPES_VS_TRANSLATIONS.put(Types.CCNodeColor, Types.NODE); TYPES_VS_TRANSLATIONS.put(Types.NS_ARRAY, Types.ARRAY); TYPES_VS_TRANSLATIONS.put(Types.NS_MUTABLE_ARRAY, Types.ARRAY); TYPES_VS_TRANSLATIONS.put(Types.NS_SET, Types.SET); TYPES_VS_TRANSLATIONS.put(Types.NS_MUTABLE_SET, Types.SET); TYPES_VS_TRANSLATIONS.put(Types.BOOL, Types.BOOL.toLowerCase()); TYPES_VS_TRANSLATIONS.put(Types.ID, Types.REF_POINTER); TYPES_VS_TRANSLATIONS.put(Types.CGPOINT, Types.VEC2); TYPES_VS_TRANSLATIONS.put(Types.CGSIZE, Types.SIZE); TYPES_VS_TRANSLATIONS.put(Types.CGRECT, Types.RECT); TYPES_VS_TRANSLATIONS.put(Types.NSUINTEGER, Types.INT); TYPES_VS_TRANSLATIONS.put(Types.NSINTEGER, Types.INT); TYPES_VS_TRANSLATIONS.put(Types.UP_FLOAT, Types.FLOAT); TYPES_VS_TRANSLATIONS.put(Types.NSDICTIONARY, Types.DICTIONARY); TYPES_VS_TRANSLATIONS.put(Types.NSMUTABLEDICTIONARY, Types.DICTIONARY); TYPES_VS_TRANSLATIONS.put(Types.CCTOUCHEVENT, Types.EVENT); TYPES_VS_TRANSLATIONS.put(Types.CCACTIONCALLFUNC, Types.CALLFUNC); TYPES_VS_TRANSLATIONS.put(Types.CCACTIONCALLFUNCO, Types.CALLFUNCO); TYPES_VS_TRANSLATIONS.put(Types.CCACTIONCALLBLOCK, Types.CALLFUNC); TYPES_VS_TRANSLATIONS.put(Types.CCACTIONDELAY, Types.DELAYTIME); TYPES_VS_TRANSLATIONS.put(Types.CCACTIONSEQUENCE, Types.SEQUENCE); TYPES_VS_TRANSLATIONS.put(Types.CCCOLOR, Types.MAKKAJAICOLOR); TYPES_VS_TRANSLATIONS.put(Types.CCLABELTTF, Types.LABEL); TYPES_VS_TRANSLATIONS.put(Types.NSNOTIFICATIONCENTER, Types.__NOTIFICATIONCENTER); TYPES_VS_TRANSLATIONS.put(Types.NSNUMBER, Types.__INTEGER); TYPES_VS_TRANSLATIONS.put(Types.SEL, Types.SEL_CALLFUNCO); METHODS_VS_TRANSLATIONS.put(Methods.STRING_WITH_FORMAT, Methods.CREATE_WITH_FORMAT); METHODS_VS_TRANSLATIONS.put(Methods.CCP, Methods.VEC2); METHODS_VS_TRANSLATIONS.put(Methods.CG_RECT_MAKE, Methods.RECT); METHODS_VS_TRANSLATIONS.put(Methods.CG_SIZE_MAKE, Methods.SIZE); METHODS_VS_TRANSLATIONS.put(Methods.ACTIONWITHBLOCK, Methods.CREATE); METHODS_VS_TRANSLATIONS.put(Methods.ACTIONWITHDURATION, Methods.CREATE); METHODS_VS_TRANSLATIONS.put(Methods.ACTIONONETWO, Methods.CREATEWITHTWOACTIONS); METHODS_VS_TRANSLATIONS.put(Methods.NODE, Methods.CREATE); METHODS_VS_TRANSLATIONS.put(Methods.ADDCHILDZ, Methods.ADDCHILD); METHODS_VS_TRANSLATIONS.put(Methods.SCHEDULEINTERVAL, Methods.SCHEDULE); METHODS_VS_TRANSLATIONS.put(Methods.ALLOC, Methods.CREATE); METHODS_VS_TRANSLATIONS.put(Methods.LABELWITHSTRING_FONTNAME_FONTSIZE, Methods.CREATEWITHTTF); METHODS_VS_TRANSLATIONS.put(Methods.ADDOBSERVER_SELECTOR_NAME_OBJECT, Methods.ADDOBSERVER); METHODS_VS_TRANSLATIONS.put(Methods.ADDCHILDNAME, Methods.ADDCHILD); METHODS_VS_TRANSLATIONS.put(Methods.ADDCHILDTAG, Methods.ADDCHILD); METHODS_VS_TRANSLATIONS.put(Methods.REMOVECHILDCLEANUP, Methods.REMOVECHILD); METHODS_VS_TRANSLATIONS.put(Methods.REMOVECHILDBYTAGCLEANUP, Methods.REMOVECHILDBYTAG); METHODS_VS_TRANSLATIONS.put(Methods.VIEWSIZE, Methods.GETWINSIZE); METHODS_VS_TRANSLATIONS.put(Methods.RUNNINGSCENE, Methods.GETRUNNINGSCENE); METHODS_VS_TRANSLATIONS.put(Methods.COPY, Methods.CLONE); METHODS_VS_TRANSLATIONS.put(Methods.OBJECTFORKEY, Methods.VALUEFORKEY); METHODS_VS_TRANSLATIONS.put(Methods.SETOBJECTFORKEY, Methods.SETOBJECT); instanceVariables = new ArrayList<String>(); methodSignatures = new ArrayList<String>(); } void translateFile(final TranslateFileInput translateFileInput) throws IOException { if (translateFileInput.filePathRelativeToInput.contains("IconWithText")) { System.out.println("Break!"); } initializeVariables(translateFileInput); startParsing(translateFileInput); writeOutput(translateFileInput); } private void initializeVariables(final TranslateFileInput translateFileInput) throws IOException { //The input file to parse! File file = new File(translateFileInput.getAbsoluteInputFilePath()); fileName = file.getName(); //Getting the lexer. ObjCLexer lexer = new ObjCLexer(new ANTLRInputStream(new FileInputStream(file))); //This is the single most important guy. Useful in getting the source set of tokens and stuff. tokens = new CommonTokenStream(lexer); outputBuffer = new StringBuilder().append(tokens.getText()); sourceVsDestinationText = new Hashtable<String, String>(); if (!isHeaderFile()) { instanceVariables.clear(); } if (isHeaderFile() && translateFileInput.dryRun) { methodSignatures.clear(); } } private void startParsing(final TranslateFileInput translateFileInput) { //Parser obviously. ObjCParser parser = new ObjCParser(tokens); ParseTree tree = parser.translation_unit(); //This is where the entire file is parsed and appropreat callbacks are made to parse the input file. visit(tree); } private void writeOutput(final TranslateFileInput translateFileInput) throws IOException { //All done, lets write the output buffer to the output file and get done with it! if (translateFileInput.dryRun) return; File outputFile = new File(translateFileInput.getAbsoluteOutputFilePath()); outputFile.getParentFile().mkdirs(); FileWriter outputFileWriter = new FileWriter(outputFile); outputFileWriter.write(translateKeywords(getFileHeader() + outputBuffer.toString())); outputFileWriter.flush(); outputFileWriter.close(); } @Override public Void visitPreprocessor_declaration(ObjCParser.Preprocessor_declarationContext ctx) { String importText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(importText); if (startIndex < 0) return super.visitPreprocessor_declaration(ctx); int endIndex = startIndex + importText.length(); String fileToImport = importText.replaceAll(Keywords.IMPORT, EMPTY_STRING); Pattern pattern = Pattern.compile("((\"(.*)\")|(<(.*)>))\\W"); Matcher matcher = pattern.matcher(fileToImport); if (!matcher.matches()) { return super.visitPreprocessor_declaration(ctx); } String headerFileName = matcher.group(3) == null ? matcher.group(5) : matcher.group(3); boolean isWithAngleBrackets = matcher.group(3) == null; String[] parts = headerFileName.split("/"); headerFileName = isWithAngleBrackets ? "<" : "\""; for (int i = 0; i < parts.length; i++) { if (i > 0) { headerFileName += "/"; } headerFileName += parts[i]; } headerFileName += (isWithAngleBrackets ? ">" : "\"") + "\n"; //Ignoring certain headers. if (importText.contains("Foundation/Foundation.h") || importText.contains("ReflectionKit.h") || importText.contains("CoreGraphics.h") || importText.contains("OverlayEffects.h") || importText.contains("MultipeerConnectivity/MultipeerConnectivity.h") || importText.contains("GameKit/GameKit.h")) writeToOutputBuffer(startIndex, endIndex, importText, "#include \"cocos2d.h\"\n", true); else writeToOutputBuffer(startIndex, endIndex, importText, Keywords.INCLUDE + headerFileName, true); return super.visitPreprocessor_declaration(ctx); } @Override public Void visitClass_list(ObjCParser.Class_listContext ctx) { String classListText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(classListText); if (startIndex < 0) return super.visitClass_list(ctx); List<ObjCParser.Class_nameContext> class_nameContexts = ctx.class_name(); for (ObjCParser.Class_nameContext classNameContext : class_nameContexts) { String sourceClassName = tokens.getText(classNameContext); String translatedClassName = translateIdentifier(sourceClassName); int startClassNameIndex = outputBuffer.indexOf(sourceClassName, startIndex); writeToOutputBuffer(startClassNameIndex, startClassNameIndex + sourceClassName.length(), sourceClassName, translatedClassName, true); } return super.visitClass_list(ctx); } @Override public Void visitProtocol_declaration_list(ObjCParser.Protocol_declaration_listContext ctx) { String protocolListText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(protocolListText); if (startIndex < 0) return super.visitProtocol_declaration_list(ctx); List<ObjCParser.Protocol_nameContext> protocol_nameContexts = ctx.protocol_list().protocol_name(); for (ObjCParser.Protocol_nameContext protocolNameContext : protocol_nameContexts) { String sourceClassName = tokens.getText(protocolNameContext); String translatedClassName = translateIdentifier(sourceClassName); int startClassNameIndex = outputBuffer.indexOf(sourceClassName, startIndex); writeToOutputBuffer(startClassNameIndex, startClassNameIndex + sourceClassName.length(), sourceClassName, translatedClassName, true); } return super.visitProtocol_declaration_list(ctx); } @Override public Void visitProtocol_declaration(ObjCParser.Protocol_declarationContext ctx) { String protocolInterfaceText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(protocolInterfaceText); int startEndIndexIndex = outputBuffer.lastIndexOf(Keywords.END); if (startIndex < 0) return super.visitProtocol_declaration(ctx); isProtocol = true; className = ctx.protocol_name().IDENTIFIER().getText(); superClassName = null; categoryClassName = null; int indexOfFirstNewLine = outputBuffer.indexOf("\n", startIndex); int indexOfBrace = outputBuffer.indexOf("{", startIndex); int finalIndexToConsider = (indexOfBrace >= 0) ? indexOfBrace : indexOfFirstNewLine; String suffix = (indexOfBrace >= 0) ? EMPTY_STRING : "{"; className = translateIdentifier(className); superClassName = translateIdentifier(superClassName); outputBuffer .replace(startEndIndexIndex, startEndIndexIndex + Keywords.END.length(), String.format("\n\n};\n\n#endif // __%s_H__", className.toUpperCase())) .replace(startIndex, finalIndexToConsider, translateClassDeclaration(ctx.protocol_reference_list()) + suffix + "\n\npublic:\n\n"); return super.visitProtocol_declaration(ctx); } @Override public Void visitClass_interface(ObjCParser.Class_interfaceContext ctx) { String classInterfaceText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(classInterfaceText); int startEndIndexIndex = outputBuffer.indexOf(Keywords.END); if (startIndex < 0) return super.visitClass_interface(ctx); isProtocol = false; className = ctx.class_name().IDENTIFIER().getText(); superClassName = ctx.superclass_name().IDENTIFIER().getText(); categoryClassName = null; int indexOfFirstNewLine = outputBuffer.indexOf("\n", startIndex); int indexOfBrace = outputBuffer.indexOf("{", startIndex); int finalIndexToConsider = (indexOfBrace >= 0) ? indexOfBrace : indexOfFirstNewLine; String suffix = ((indexOfBrace >= 0) ? EMPTY_STRING : "{\n\npublic:\n\n"); className = translateIdentifier(className); superClassName = translateIdentifier(superClassName); outputBuffer.replace(startEndIndexIndex, startEndIndexIndex + Keywords.END.length(), String.format("\nCREATE_FUNC(%s);\n\n%s\n\n};\n\n#endif // __%s_H__", className, translatePrivateMethodsDeclaration(), className.toUpperCase())) .replace(startIndex, finalIndexToConsider, translateClassDeclaration(ctx.protocol_reference_list()) + suffix); return super.visitClass_interface(ctx); } @Override public Void visitCategory_interface(ObjCParser.Category_interfaceContext ctx) { String classInterfaceText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(classInterfaceText); int startEndIndexIndex = outputBuffer.indexOf(Keywords.END); if (startIndex < 0) return super.visitCategory_interface(ctx); isProtocol = false; className = ctx.class_name().IDENTIFIER().getText(); superClassName = null; categoryClassName = ctx.category_name() != null ? ctx.category_name().IDENTIFIER().getText() : null; int indexOfFirstNewLine = outputBuffer.indexOf("\n", startIndex); int indexOfBrace = outputBuffer.indexOf("{", startIndex); int finalIndexToConsider = (indexOfBrace >= 0) ? indexOfBrace : indexOfFirstNewLine; String suffix = ((indexOfBrace >= 0) ? EMPTY_STRING : "{\n\npublic:\n\n"); className = translateIdentifier(className); categoryClassName = translateIdentifier(categoryClassName); outputBuffer.replace(startEndIndexIndex, startEndIndexIndex + Keywords.END.length(), String.format("\nCREATE_FUNC(%s);\n\n%s\n\n};\n\n#endif // __%s_H__", className, translatePrivateMethodsDeclaration(), className.toUpperCase())) .replace(startIndex, finalIndexToConsider, translateClassDeclaration(ctx.protocol_reference_list()) + suffix); return super.visitCategory_interface(ctx); } @Override public Void visitClass_implementation(ObjCParser.Class_implementationContext ctx) { String classImplementationText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(classImplementationText); int startEndIndexIndex = outputBuffer.indexOf(Keywords.END); if (startIndex < 0) return super.visitClass_implementation(ctx); isProtocol = false; String originalClassName = ctx.class_name().getText(); className = translateIdentifier(originalClassName); superClassName = ctx.superclass_name() != null ? ctx.superclass_name().getText() : superClassName; categoryClassName = null; int startClassNameIndex = outputBuffer.indexOf(originalClassName, startIndex); int endClassNameIndex = startClassNameIndex + originalClassName.length(); outputBuffer.replace(startEndIndexIndex, startEndIndexIndex + Keywords.END.length(), EMPTY_STRING) .replace(startIndex, endClassNameIndex, USING_NS_CC); className = translateIdentifier(className); superClassName = translateIdentifier(superClassName); return super.visitClass_implementation(ctx); } @Override public Void visitCategory_implementation(ObjCParser.Category_implementationContext ctx) { String classImplementationText = tokens.getText(ctx.getSourceInterval()); int startIndex = outputBuffer.indexOf(classImplementationText); int startEndIndexIndex = outputBuffer.indexOf(Keywords.END); if (startIndex < 0) return super.visitCategory_implementation(ctx); isProtocol = false; String originalClassName = ctx.class_name().getText(); className = translateIdentifier(originalClassName); superClassName = null; categoryClassName = ctx.category_name() != null ? ctx.category_name().IDENTIFIER().getText() : null; int startCategoryNameIndex = outputBuffer.indexOf(categoryClassName, startIndex); int endClassNameIndex = startCategoryNameIndex + categoryClassName.length() + 1; outputBuffer.replace(startEndIndexIndex, startEndIndexIndex + Keywords.END.length(), EMPTY_STRING) .replace(startIndex, endClassNameIndex, USING_NS_CC); categoryClassName = translateIdentifier(categoryClassName); className = translateIdentifier(className) + (categoryClassName != null ? "_" + categoryClassName : ""); return super.visitCategory_implementation(ctx); } @Override public Void visitClass_method_declaration(ObjCParser.Class_method_declarationContext ctx) { String methodBody = tokens.getText(ctx.getSourceInterval()); int startMethodBody = outputBuffer.indexOf(methodBody); startMethodBody = outputBuffer.lastIndexOf("+", startMethodBody); if (startMethodBody < 0) { return super.visitClass_method_declaration(ctx); } ObjCParser.Method_declarationContext method_declarationContext = ctx.method_declaration(); translateMethodDefination(method_declarationContext.method_type(), method_declarationContext.method_selector(), tokens.getText(method_declarationContext), startMethodBody, "static ", false); return super.visitClass_method_declaration(ctx); } @Override public Void visitInstance_method_declaration(ObjCParser.Instance_method_declarationContext ctx) { String methodBody = tokens.getText(ctx.getSourceInterval()); int startMethodBody = outputBuffer.indexOf(methodBody); startMethodBody = outputBuffer.lastIndexOf("-", startMethodBody); if (startMethodBody < 0) { return super.visitInstance_method_declaration(ctx); } ObjCParser.Method_declarationContext method_declarationContext = ctx.method_declaration(); translateMethodDefination(method_declarationContext.method_type(), method_declarationContext.method_selector(), tokens.getText(method_declarationContext), startMethodBody, "virtual ", false); return super.visitInstance_method_declaration(ctx); } @Override public Void visitInstance_method_definition(ObjCParser.Instance_method_definitionContext ctx) { String methodBody = tokens.getText(ctx.getSourceInterval()); int startMethodBody = outputBuffer.indexOf(methodBody); startMethodBody = outputBuffer.lastIndexOf("-", startMethodBody); if (startMethodBody < 0) { return super.visitInstance_method_definition(ctx); } translateMethodDefination(ctx.method_definition().method_type(), ctx.method_definition().method_selector(), tokens.getText(ctx), startMethodBody, "virtual ", true); isProcessingInstanceMethod = true; return super.visitInstance_method_definition(ctx); } @Override public Void visitClass_method_definition(ObjCParser.Class_method_definitionContext ctx) { String methodBody = tokens.getText(ctx.getSourceInterval()); int startMethodBody = outputBuffer.indexOf(methodBody); startMethodBody = outputBuffer.lastIndexOf("+", startMethodBody); if (startMethodBody < 0) { return super.visitClass_method_definition(ctx); } translateMethodDefination(ctx.method_definition().method_type(), ctx.method_definition().method_selector(), tokens.getText(ctx), startMethodBody, "static ", true); isProcessingInstanceMethod = false; return super.visitClass_method_definition(ctx); } @Override public Void visitBlock_expression(ObjCParser.Block_expressionContext ctx) { String sourceText = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceText); if (start < 0) { return super.visitBlock_expression(ctx); } int indexOfBrace = sourceText.indexOf("{"); String finalParameterTypeAndName = EMPTY_STRING; List<ObjCParser.Type_variable_declaratorContext> typeVariableDeclaratorContexts = ctx .block_parameters() == null ? new ArrayList<ObjCParser.Type_variable_declaratorContext>() : ctx.block_parameters().type_variable_declarator(); for (ObjCParser.Type_variable_declaratorContext typeVariableDeclaratorContext : typeVariableDeclaratorContexts) { VariableTypeNameInfo variableTypeNameInfo = translateTypeVariableDeclarator( typeVariableDeclaratorContext); if (!finalParameterTypeAndName.equals(EMPTY_STRING)) { finalParameterTypeAndName += ", "; } finalParameterTypeAndName += variableTypeNameInfo.variableType + variableTypeNameInfo.pointer + " " + variableTypeNameInfo.variableName; } writeToOutputBuffer(start, start + indexOfBrace, sourceText.substring(0, indexOfBrace), "[] (" + finalParameterTypeAndName + ") ", true); return super.visitBlock_expression(ctx); } @Override public Void visitProperty_declaration(ObjCParser.Property_declarationContext ctx) { String sourceText = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceText); if (start < 0) { return super.visitProperty_declaration(ctx); } String type = tokens.getText(ctx.struct_declaration().specifier_qualifier_list()); String variable = tokens.getText(ctx.struct_declaration().struct_declarator_list()); String finalPropertyText = EMPTY_STRING; String translatedIdentifier = translateIdentifier(type); if (variable.contains(ASTERISK)) { finalPropertyText += CC_SYNTHESIZE + translatedIdentifier + ASTERISK; } else if (type.startsWith(Constants.ID)) { finalPropertyText += CC_SYNTHESIZE + translatedIdentifier; } else { finalPropertyText += CC_SYNTHESIZE_PASS_BY_REF + translatedIdentifier; } String transformedVariable = variable.replace('*', ' ').trim(); finalPropertyText += ", " + transformedVariable + ", " + toUpperFirstLetter(transformedVariable) + ");"; writeToOutputBuffer(start, start + sourceText.length(), sourceText, finalPropertyText, true); return super.visitProperty_declaration(ctx); } @Override public Void visitProperty_implementation(ObjCParser.Property_implementationContext ctx) { String sourcePropertyImplementation = tokens.getText(ctx); int start = outputBuffer.indexOf(sourcePropertyImplementation); if (start < 0) { return super.visitProperty_implementation(ctx); } writeToOutputBuffer(start, start + sourcePropertyImplementation.length(), sourcePropertyImplementation, "", true); return super.visitProperty_implementation(ctx); } @Override public Void visitInstance_variables(ObjCParser.Instance_variablesContext ctx) { String sourceInstanceVariables = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceInstanceVariables); if (start < 0) { return super.visitInstance_variables(ctx); } ObjCParser.Visibility_specificationContext visibilitySpecificationContext = ctx.visibility_specification(); if (visibilitySpecificationContext != null) instanceVariables.add(tokens.getText(visibilitySpecificationContext)); for (ObjCParser.Struct_declarationContext structDeclarationContext : ctx.struct_declaration()) { String type = tokens.getText(structDeclarationContext.specifier_qualifier_list()); String variable = tokens.getText(structDeclarationContext.struct_declarator_list()); instanceVariables.add(translateIdentifier(type) + " " + variable + ";"); } if (!isHeaderFile()) { writeToOutputBuffer(start, start + sourceInstanceVariables.length(), sourceInstanceVariables, EMPTY_STRING, true); return super.visitInstance_variables(ctx); } String finalInstanceVariables = "{\n\n"; for (final String variable : instanceVariables) { finalInstanceVariables += variable + "\n"; } finalInstanceVariables += "\npublic:"; writeToOutputBuffer(start, start + sourceInstanceVariables.length(), sourceInstanceVariables, finalInstanceVariables, true); return super.visitInstance_variables(ctx); } @Override public Void visitPrimary_expression(ObjCParser.Primary_expressionContext ctx) { if (ctx.STRING_LITERAL() != null) { String sourceString = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceString); if (start < 0) { return super.visitPrimary_expression(ctx); } writeToOutputBuffer(start, start + sourceString.length(), sourceString, "cocos2d::__String::create(" + sourceString.substring(0, 1) + "TOBEDELETED_TEMP_STRING" + sourceString.substring(1) + ")", true); return super.visitPrimary_expression(ctx); } return super.visitPrimary_expression(ctx); } @Override public Void visitDeclaration(ObjCParser.DeclarationContext ctx) { String sourceDeclaration = tokens.getText(ctx.getSourceInterval()); int start = outputBuffer.indexOf(sourceDeclaration); if (start < 0) { return super.visitDeclaration(ctx); } String declarationSpecifierSourceText = tokens.getText(ctx.declaration_specifiers().getSourceInterval()); int startDeclarationSpecifier = outputBuffer.indexOf(sourceDeclaration, start); writeToOutputBuffer(startDeclarationSpecifier, startDeclarationSpecifier + declarationSpecifierSourceText.length(), declarationSpecifierSourceText, translateIdentifier(declarationSpecifierSourceText), false); return super.visitDeclaration(ctx); } @Override public Void visitMessage_expression(ObjCParser.Message_expressionContext ctx) { String sourceText = tokens.getText(ctx.getSourceInterval()); int start = outputBuffer.indexOf(sourceText); if (start < 0) { return super.visitMessage_expression(ctx); } int end = start + sourceText.length(); String receiver = translateIdentifier(tokens.getText(ctx.receiver().getSourceInterval())); String finalMethod = "(" + receiver + translateInvocationOperator(receiver); finalMethod += translateMethodNameAndParameters(ctx.message_selector()) + ")"; writeToOutputBuffer(start, end, sourceText, finalMethod, true); return super.visitMessage_expression(ctx); } @Override public Void visitSelector_expression(ObjCParser.Selector_expressionContext ctx) { String sourceText = tokens.getText(ctx.getSourceInterval()); int start = outputBuffer.indexOf(sourceText); if (start < 0) { return super.visitSelector_expression(ctx); } String macroToUse = CC_CALLBACK + (sourceText.length() - sourceText.replace(":", EMPTY_STRING).length()) + "("; List<ObjCParser.SelectorContext> selectorParts = ctx.selector_name().selector(); String finalMethodName = EMPTY_STRING; for (ObjCParser.SelectorContext selector : selectorParts) { String currentSelectorPart = tokens.getText(selector); finalMethodName += finalMethodName.equals(EMPTY_STRING) ? translateMethodName(currentSelectorPart) : toUpperFirstLetter(currentSelectorPart); } writeToOutputBuffer(start, start + sourceText.length(), sourceText, macroToUse + className + STATIC_INVOCATION_OPERATOR + translateMethodName(finalMethodName) + ", this)", true); return super.visitSelector_expression(ctx); } @Override public Void visitAssignment_expression(ObjCParser.Assignment_expressionContext ctx) { String sourceText = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceText); if (start < 0 || ctx.assignment_operator() == null || ctx.unary_expression() == null || ctx.unary_expression().postfix_expression() == null) return super.visitAssignment_expression(ctx); String postFixSetterExpression = visitPostFixExpression(ctx.unary_expression().postfix_expression(), true); if (!postFixSetterExpression.contains("(")) return super.visitAssignment_expression(ctx); String postFixGetterExpression = visitPostFixExpression(ctx.unary_expression().postfix_expression(), false); String assignmentRHS = tokens.getText(ctx.assignment_expression()); String assignmentOperator = tokens.getText(ctx.assignment_operator()); assignmentOperator = assignmentOperator.replace("=", ""); //What we are eseentially doing here is just adding a placeholder so that it can be replaced during further processing by other callback methods. String finalExpression = "(" + tokens.getText(ctx.unary_expression()) + SETTER_PLACEHOLDER; if (assignmentOperator.trim().equals("")) { finalExpression += assignmentRHS + "))"; } else { finalExpression += postFixGetterExpression + " " + assignmentOperator + " " + assignmentRHS + "))"; } writeToOutputBuffer(start, start + sourceText.length(), sourceText, finalExpression, true); return super.visitAssignment_expression(ctx); } @Override public Void visitPostfix_expression(ObjCParser.Postfix_expressionContext ctx) { String sourceText = tokens.getText(ctx); int start = outputBuffer.indexOf(sourceText); if (start < 0 || !(ctx.identifier() != null && ctx.identifier().size() > 0)) return super.visitPostfix_expression(ctx); int endIndex = start + (sourceText + SETTER_PLACEHOLDER).length(); endIndex = outputBuffer.length() <= endIndex ? outputBuffer.length() - 1 : endIndex; boolean isSetter = outputBuffer.substring(start, endIndex).contains(SETTER_PLACEHOLDER); String finalExpression = visitPostFixExpression(ctx, isSetter); writeToOutputBuffer(start, start + (isSetter ? (sourceText + SETTER_PLACEHOLDER).length() : sourceText.length()), sourceText, finalExpression, true); return super.visitPostfix_expression(ctx); } public String visitPostFixExpression(ObjCParser.Postfix_expressionContext ctx, boolean isSetter) { String finalExpression = EMPTY_STRING; for (int i = 0; i < ctx.children.size(); i++) { String nodeText = tokens.getText(ctx.children.get(i).getSourceInterval()); if (ctx.children.get(i) instanceof ObjCParser.IdentifierContext) { finalExpression += ((isSetter && i == ctx.children.size() - 1) ? "set" : "get") + toUpperFirstLetter(nodeText) + ((isSetter && i == ctx.children.size() - 1) ? "(" : "()"); finalExpression = (isSetter ? "" : "(") + finalExpression + (isSetter ? "" : ")"); } else { if (nodeText.equals(".")) { nodeText = INSTANCE_INVOCATION_OPERATOR; } finalExpression += nodeText; } } return finalExpression; } @Override public Void visitFor_in_statement(ObjCParser.For_in_statementContext ctx) { String sourceForLoop = tokens.getText(ctx); int startForLoop = outputBuffer.indexOf(sourceForLoop); if (startForLoop < 0) { return super.visitFor_in_statement(ctx); } int indexOfPreviousNewline = outputBuffer.lastIndexOf("\n", startForLoop); int indexOfFirstNewLine = sourceForLoop.indexOf("\n"); String whitespaceSeparator = outputBuffer.substring(indexOfPreviousNewline, startForLoop); String whitespaceSeparatorInLoop = sourceForLoop.substring(indexOfFirstNewLine + 1, indexOfFirstNewLine + sourceForLoop.substring(indexOfFirstNewLine).length() - sourceForLoop.substring(indexOfFirstNewLine).trim().length()); VariableTypeNameInfo variableTypeNameInfo = translateTypeVariableDeclarator(ctx.type_variable_declarator()); String variableNameWithRef = variableTypeNameInfo.variableName + "_ref"; //Please forgive me for this ugly code to also take care of intend. String finalForLoop = Types.REF_POINTER + " " + variableNameWithRef + ";" + whitespaceSeparator + CCARRAY_FOREACH + tokens.getText(ctx.expression()) + ", " + variableNameWithRef + ") {\n" + whitespaceSeparatorInLoop + variableTypeNameInfo.variableType + " " + variableTypeNameInfo.pointer + variableTypeNameInfo.variableName + DYNAMIC_CAST + variableTypeNameInfo.variableType + variableTypeNameInfo.pointer + ">(" + variableNameWithRef + ");"; writeToOutputBuffer(startForLoop, startForLoop + sourceForLoop.length(), sourceForLoop, finalForLoop + sourceForLoop.substring(indexOfFirstNewLine), true); return super.visitFor_in_statement(ctx); } private String translateIdentifier(String identifier) { if (identifier == null) return null; Pattern beginsWithUpperCaseLetters = Pattern.compile(BEGINS_WITH_2_UPPER_CASE_LETTERS); Pattern beginsWithId = Pattern.compile(BEGINS_WITH_ID); Matcher matcherForUpperCaseLetters = beginsWithUpperCaseLetters.matcher(identifier); Matcher matcherForId = beginsWithId.matcher(identifier); boolean matchesUpperCaseLetters = matcherForUpperCaseLetters.matches(); boolean matchesId = matcherForId.matches(); if (matchesId) { String protocolName = matcherForId.group(1); return translateIdentifier(protocolName) + " * "; } for (final String key : Collections.list(TYPES_VS_TRANSLATIONS.keys())) { if (identifier.startsWith(key)) { return identifier.replace(key, TYPES_VS_TRANSLATIONS.get(key)); } } if (identifier.startsWith(CC)) { return COCOS2D + matcherForUpperCaseLetters.group(2); } if (matchesUpperCaseLetters) { return matcherForUpperCaseLetters.group(2); } if (identifier.startsWith(Keywords.SELF) && !isProcessingInstanceMethod) { return className; } return identifier; } private String translateMethodName(String identifier) { if (identifier == null) return null; for (final String key : Collections.list(METHODS_VS_TRANSLATIONS.keys())) { if (identifier.startsWith(key)) { return identifier.replace(key, METHODS_VS_TRANSLATIONS.get(key)); } } return identifier; } private String translateInvocationOperator(String receiver) { Pattern pattern = Pattern.compile(BEGINS_WITH_UPPER_CASE_LETTERS); Matcher matcher = pattern.matcher(receiver.replaceAll(COCOS2D, EMPTY_STRING)); if (receiver.isEmpty()) return EMPTY_STRING; else if (matcher.matches()) { //Looks like we are making a static call. return STATIC_INVOCATION_OPERATOR; } return INSTANCE_INVOCATION_OPERATOR; } private String translateMethodNameAndParameters(ObjCParser.Message_selectorContext messageSelectorContext) { String finalMethodName = EMPTY_STRING; String finalParameters = EMPTY_STRING; //If this is just a method with no keyword argument we need to get just the selector and use it as the method name. if (messageSelectorContext.keyword_argument().size() == 0) { finalMethodName = tokens.getText(messageSelectorContext.selector().getSourceInterval()); } //Well this method is made up of multiple parts we will need to upper case the subsequent parts to follow Camel case convention //and then pass the parameters as method call. for (int i = 0; i < messageSelectorContext.keyword_argument().size(); i++) { ObjCParser.Keyword_argumentContext keyword_argumentContext = messageSelectorContext.keyword_argument() .get(i); ObjCParser.SelectorContext selector = keyword_argumentContext.selector(); String sourceMethod = selector == null ? EMPTY_STRING : tokens.getText(selector.getSourceInterval()); String sourceParameter = tokens.getText(keyword_argumentContext.expression().getSourceInterval()); if (i > 0) { sourceMethod = toUpperFirstLetter(sourceMethod); finalParameters += ", "; } finalMethodName += translateMethodName(sourceMethod); finalParameters += sourceParameter; } return translateMethodName(finalMethodName) + "(" + finalParameters + ")"; } private void translateMethodDefination(ObjCParser.Method_typeContext method_typeContext, ObjCParser.Method_selectorContext method_selectorContext, String sourceText, int startMethodBody, String methodPrefix, boolean shouldAddClassname) { String sourceMethodTypeString = tokens.getText(method_typeContext.getSourceInterval()); String methodTypeString = tokens.getText(method_typeContext.getSourceInterval()); int startMethodType = outputBuffer.indexOf(methodTypeString, startMethodBody); int endMethodType = startMethodType + methodTypeString.length(); String methodTypeSanitized = methodTypeString.replaceAll("\\(", EMPTY_STRING).replaceAll("\\)", " "); String finalMethodNameParameterTypeAndNamesWithoutClassNamePrefix = translateMethodNameParameterTypeAndNames( method_selectorContext); methodTypeString = (shouldAddClassname ? "" : methodPrefix) + translateIdentifier( finalMethodNameParameterTypeAndNamesWithoutClassNamePrefix.startsWith(INIT) ? Types.BOOL + " " : methodTypeSanitized); writeToOutputBuffer(startMethodBody, endMethodType, sourceMethodTypeString, methodTypeString, false); String classNamePrefix = shouldAddClassname ? className + "::" : EMPTY_STRING; String finalMethodNameParameterTypeAndNames = classNamePrefix + finalMethodNameParameterTypeAndNamesWithoutClassNamePrefix; String finalMethodTypeNameParameterTypeAndNames = (shouldAddClassname ? methodPrefix : "") + methodTypeString + finalMethodNameParameterTypeAndNamesWithoutClassNamePrefix; String methodSelectorString = tokens.getText(method_selectorContext.getSourceInterval()); int startMethodSelector = outputBuffer.indexOf(methodSelectorString, startMethodBody); int endMethodSelector = startMethodSelector + methodSelectorString.length(); if (methodSignatures.contains(finalMethodTypeNameParameterTypeAndNames)) { methodSignatures.remove(finalMethodTypeNameParameterTypeAndNames); } else { methodSignatures.add(finalMethodTypeNameParameterTypeAndNames); } writeToOutputBuffer(startMethodSelector, endMethodSelector, sourceText, finalMethodNameParameterTypeAndNames, true); } private String translateMethodNameParameterTypeAndNames( ObjCParser.Method_selectorContext methodSelectorContext) { String finalMethodName = EMPTY_STRING; String finalParameters = EMPTY_STRING; //If this is just a method with no keyword argument we need to get just the selector and use it as the method name. if (methodSelectorContext.keyword_declarator().size() == 0) { finalMethodName = tokens.getText(methodSelectorContext.selector().getSourceInterval()); } //Well this method is made up of multiple parts we will need to upper case the subsequent parts to follow Camel case convention //and then pass the parameters as method call. for (int i = 0; i < methodSelectorContext.keyword_declarator().size(); i++) { ObjCParser.Keyword_declaratorContext keyword_declaratorContext = methodSelectorContext .keyword_declarator().get(i); ObjCParser.SelectorContext selector = keyword_declaratorContext.selector(); String sourceMethod = selector == null ? EMPTY_STRING : tokens.getText(selector.getSourceInterval()); String sourceType = tokens.getText(keyword_declaratorContext.method_type(0).getSourceInterval()); String sourceParameter = tokens.getText(keyword_declaratorContext.IDENTIFIER().getSourceInterval()); if (i > 0) { sourceMethod = toUpperFirstLetter(sourceMethod); finalParameters += ", "; } finalMethodName += sourceMethod; finalParameters += translateIdentifier( sourceType.replaceAll("\\(", EMPTY_STRING).replaceAll("\\)", EMPTY_STRING)) + " " + sourceParameter; } return finalMethodName + "(" + finalParameters + ")" + (isProtocol ? PURE_VIRTUAL_METHOD_POSTFIX : EMPTY_STRING); } private String translateKeywords(String source) { //Final set of translations to get rid of the imports and supers and self and nil. for (final String key : Collections.list(sourceVsDestinationText.keys())) { if (sourceVsDestinationText.get(key).contains(key)) continue; while (source.contains(key)) { source = source.replace(key, sourceVsDestinationText.get(key)); } } KEYWORDS_VS_TRANSLATIONS.remove(Keywords.SUPER); KEYWORDS_VS_TRANSLATIONS.put(Types.INSTANCETYPE, className + " " + ASTERISK); KEYWORDS_VS_TRANSLATIONS.put(Keywords.SUPER + INSTANCE_INVOCATION_OPERATOR, superClassName + STATIC_INVOCATION_OPERATOR); for (final String key : Collections.list(KEYWORDS_VS_TRANSLATIONS.keys())) { source = source.replaceAll(key, KEYWORDS_VS_TRANSLATIONS.get(key)); } return source; } private String getFileHeader() { return "/**\n" + " * Autogenerated by ObjCToCppTranslator on " + new SimpleDateFormat("dd/MM/yyyy").format(new Date()) + "\n" + " * @author Deep Shah\n" + " * (c) 2015 Makkajai\n" + " * This code is licensed under MIT license (see LICENSE.txt for details)\n" + " */\n\n" + getIfnDefForHeaderFiles(); } private String getIfnDefForHeaderFiles() { if (!isHeaderFile()) return EMPTY_STRING; return String.format("#ifndef __%s_H__\n#define __%s_H__\n\n", className.toUpperCase(), className.toUpperCase()); } private String translateClassDeclaration( ObjCParser.Protocol_reference_listContext protocol_reference_listContext) { String classDeclaration = CLASS + translateIdentifier(className) + " :" + translateSuperClassDeclaration(superClassName); if (categoryClassName != null) { classDeclaration = CLASS + translateIdentifier(className) + "_" + translateIdentifier(categoryClassName) + " : " + translateSuperClassDeclaration(className); } if (protocol_reference_listContext != null) { String separator = superClassName != null ? "," : EMPTY_STRING; List<ObjCParser.Protocol_nameContext> protocol_nameContexts = protocol_reference_listContext .protocol_list().protocol_name(); for (ObjCParser.Protocol_nameContext protocol_nameContext : protocol_nameContexts) { classDeclaration += separator + translateSuperClassDeclaration( translateIdentifier(protocol_nameContext.IDENTIFIER().getText())); separator = ","; } } return classDeclaration + " "; } private String translateSuperClassDeclaration(String cName) { if (cName == null) { return EMPTY_STRING; } return " public " + translateIdentifier(cName); } private String toUpperFirstLetter(final String sourceMethod) { return sourceMethod != null && sourceMethod.length() > 0 ? sourceMethod.substring(0, 1).toUpperCase() + sourceMethod.substring(1) : EMPTY_STRING; } private boolean isHeaderFile() { return fileName.endsWith(H); } private String translatePrivateMethodsDeclaration() { String finalPrivateMethodsDeclaration = "public: \n"; for (final String methodDeclaration : methodSignatures) { finalPrivateMethodsDeclaration += "\n" + methodDeclaration + ";"; } finalPrivateMethodsDeclaration += "\n"; return finalPrivateMethodsDeclaration; } private void writeToOutputBuffer(int startIndex, int endIndex, String sourceText, String destinationText, boolean shouldWriteToDictionary) { outputBuffer.replace(startIndex, endIndex, destinationText); if (shouldWriteToDictionary) sourceVsDestinationText.put(sourceText, destinationText); } private VariableTypeNameInfo translateTypeVariableDeclarator( ObjCParser.Type_variable_declaratorContext context) { VariableTypeNameInfo variableTypeNameInfo = new VariableTypeNameInfo(); variableTypeNameInfo.variableName = tokens.getText(context.declarator().direct_declarator()); variableTypeNameInfo.variableType = translateIdentifier(tokens.getText(context.declaration_specifiers())); variableTypeNameInfo.pointer = context.declarator().pointer() != null ? tokens.getText(context.declarator().pointer()) : EMPTY_STRING; return variableTypeNameInfo; } }