/* This C2J parser is able to convert C-Declarations to - Java's JNI functions declaration - The JNI C-Glue functions for native methods with the same name !! - Special support for OpenGL/GLU declarations, because C2J is developed to develop GL4Java - an OpenGL language mapping to Java !!! LGPL Licensed - copyright by Sven Goethel, 1999 Jausoft - Sven Goethel Software Development C2J based upon: =============== C grammar defintion for use with JavaCC Contributed by Doug South (dsouth@squirrel.com.au) 21/3/97 This parser assumes that the C source file has been preprocessed : all #includes have been included and all macros have been expanded. I accomplish this with "gcc -P -E > ". There is a problem with compiler specific types, such as __signed, __const, __inline__, etc. These types can be added as typedef types before the parser is run on a file. See main() for an example. I have also found a strange little compiler specific "type" if you can call it that. It is __attribute__, but it does not seem to be used as a type. I found that just deleting the __attribute__ and the following "offensive" code works. This grammar also prints out all the types defined while parsing the file. This is done via a call to printTypes() when the parser is complete. If you do not want this, just comment out the printTypes() method call in the production rule TranslationUnit(), which BTW is the root node for parsing a C source file. I have not in anyway extensively tested this grammar, in fact it is barely tested, but I imagine it is better to have a starting point for a C grammar other than from scratch. It has not been optimized in anyway, my main aim was to get a parser that works. Lookahead may not be optimum at choice points and may even be insufficient at times. I choose to err on the side of not optimum if I made a choice at all. If you use this grammar, I would appreciate hearing from you. I will try to maintain this grammar to the best of my ability, but at this point in time, this is only a side hobby (unless someone wants to pay me for doing JavaCC work!). In that regards, I am interested in hearing bugs and comments. TODO: Insert the appropiate code to enable C source trees from this grammar. */ PARSER_BEGIN(C2J) import java.util.*; public class C2J{ public static final String version = "C2J Parser Version 3.0" ; public static final String vendor = "Jausoft - Sven Goethel Software Development"; public static final int EXPORT_JNI_JAVA = 1; public static final int EXPORT_JNI_JAVA_FINAL = 2; public static final int EXPORT_MSJDIRECT_JAVA = 3; public static final int EXPORT_JNI_C = 4; // strong binding public static final int EXPORT_JNI_C_DYN = 5; // dyn. binding public static final int EXPORT_GL_FUNC_NAMES = 10; public static final int EXPORT_GL_DISPATCH_DECL= 11; public static final int EXPORT_GL_DISPATCH_VAR = 12; public static final int EXPORT_GL_DISPATCH_GET = 13; public static final int MODIFIER_JNI_CRITICAL_ARRAY = 1; public static final int MODIFIER_JNI_COPY_CHECK = 2; // experimental trial .. public static final int MODIFIER_JNI_DIRECT_BUFFERS = 4; // JDK 1.4 support public static int exportMode; public static int exportModifier; public static boolean usePointerHolderCast = false; public static boolean verbose=false ; public static boolean syntaxVerbose=false ; public static boolean echoMode=false ; public static String clazzName; public static String dllname; public static int lastEnumValue=0; // // Holder of the parsed c-code // public static String cSrc; // Hastable for storing typedef types private static Hashtable types = new Hashtable(); // Stack for determining when the parser // is parsing a typdef definition. private static Stack typedefParsingStack = new Stack(); // Returns true if the given string is // a typedef type. private static boolean isType(String type){ if(types.get(type) != null){ return true; } return false; } // Add a typedef type to those already defined private static void addType(String type){ types.put(type, Boolean.TRUE); cSrc += "\n\t/* WARNING TYPE ADDED : "+type+" */\n"; } // Prints out all the types used in parsing the c source private static void printTypes(){ Enumeration enum = types.keys(); while(enum.hasMoreElements()){ System.out.println(enum.nextElement()); } } public static void printUsage() { System.out.println("Usage is one of:"); System.out.println(" java C2J [-v] [-s] [-echo] [jnic|jnijava|jnijavaf|msjava|echo] < inputfile"); System.out.println("OR"); System.out.println(" java C2J [-v] [-s] [-echo] [-jnic-criticalarray] [-jnic-trial] [-jnic-dirbuf] [jnic|jnic-dyn|jnijava|msjava |glfnames|gldispatch-decl|gldispatch-var|gldispatch-get] inputfile"); System.out.println(" , inputfile is a C-HeaderFile (Preprocessed)."); System.out.println(" , where must be full qualified with an underscore instead of an dot - if not in (any) Java-Mode."); System.out.println(" , where -v means verbose"); System.out.println(" , where -s means including the syntax-states in Output commentary"); System.out.println(" , where -echo means including the parsed C-Code in Output commentary"); System.out.println(" , where -jnic-criticalarray includes experimental JNI-C Code"); System.out.println(" , where -jnic-trial includes experimental JNI-C Code"); System.out.println(" , where -jnic-dirbuf includes direct buffer support (JDK 1.4 and greater only)"); System.out.println(" , where jnic produces JNI-C Code (strong binding)"); System.out.println(" , where jnic-dyn produces JNI-C Code (dynamic binding)"); System.out.println(" , where jnijava produces JNI-Java Code (non final)"); System.out.println(" , where jnijavaf produces JNI-Java Code (final)"); System.out.println(" , where msjava produces MSJVM-Java Code for the DLL "); System.out.println(" , where glfnames produces all GL function names"); System.out.println(" , where gldispatch* produces the gl-func declarations, definitions and get stubs"); System.out.println(" , where echo just prints the parsed C-Code\n"); System.out.println(" E.g."); System.out.println(" java C2J jnic myPackage_myClass a.h > a.c"); System.out.println(" java C2J jnijava myPackage_myClass a.h > a.java"); System.out.println(" java C2J jnijavaf myPackage_myClass a.h > aFinalMethods.java"); System.out.println(" java C2J msjava OPENGL32 myPackage_myClass a.h > aMSVersion.java"); System.out.println(" java C2J -echo myPackage_myClass a.h > aCopy.h"); System.out.println(" ( ALL OpenGL GL's are mapped to JNI types )"); } // Run the parser public static void main ( String args [ ] ) { C2J parser ; // Hack to include type "special types" /* types.put("__signed__", Boolean.TRUE); types.put("__const", Boolean.TRUE); types.put("__inline__", Boolean.TRUE); types.put("__signed", Boolean.TRUE); */ int i; String inputFile = null; exportMode = -1; /* error */ exportModifier = 0; verbose=false; echoMode=false; if(args.length==0) { printUsage(); return; } for(i=0; i | <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/"> } TOKEN : { (["l","L"])? | (["l","L"])? | (["l","L"])?> | <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])*> | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL_LITERAL: "0" (["0"-"7"])*> | )? (["f","F","d","D"])? | "." (["0"-"9"])+ ()? (["f","F","d","D"])? | (["0"-"9"])+ (["f","F","d","D"])? | (["0"-"9"])+ ()? ["f","F","d","D"]> | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> | | } TOKEN : { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } TOKEN : { ( | )*> | <#LETTER: ["$","A"-"Z","_","a"-"z"]> | <#DIGIT: ["0"-"9"]> } void TranslationUnit() : {} { (ExternalDeclaration())+ { /* printTypes(); */ } } void ExternalDeclaration() : { CFuncDeclaration cfunc = null; } { ( LOOKAHEAD( FunctionDefinition() ) cfunc = FunctionDefinition() | cfunc = Declaration(null) ) { if(echoMode) { System.out.println("/**"); System.out.println(" * Original Function-Prototype :"); System.out.println(" *
 ");
	      System.out.print  ("   ");
	      System.out.print(cSrc);
	      System.out.println(" * 
"); System.out.println(" */"); cSrc=new String(); } if(verbose) { String tmp = new String(); tmp += "/*\n"; if(cfunc!=null) tmp += cfunc.toString(); else tmp += "NO CFUNC INSTANCE"; tmp += "\n*/"; System.out.println(tmp); } if(cfunc==null) { System.err.println("ERROR(ExternalDeclaration): no CFuncDeclaration instance received !"); return; } if(!cfunc.isValid()) { String name = null; if(cfunc.funcSpec!=null) { name=cfunc.funcSpec.identifier; if(name==null) name=cfunc.funcSpec.toString(); } if(name==null) name=""; System.err.println("WARNING(ExternalDeclaration): Function :<"+ name+"> can not be proceded - invalid !"); return; } switch(exportMode) { case EXPORT_JNI_JAVA : System.out.println(cfunc.toJniJavaCode(false, exportModifier)); break; case EXPORT_JNI_JAVA_FINAL : System.out.println(cfunc.toJniJavaCode(true, exportModifier)); break; case EXPORT_JNI_C : case EXPORT_JNI_C_DYN : System.out.println(cfunc.toJniCCode(clazzName, exportMode, exportModifier)); break; case EXPORT_GL_FUNC_NAMES: System.out.println("\t\t\""+cfunc.funcSpec.identifier+"\", "); break; case EXPORT_GL_DISPATCH_DECL: System.out.println("\tLIBAPI "+ cfunc.funcSpec.getCTypeString()+ " (CALLBACK * disp__"+ cfunc.funcSpec.identifier + " )("+ cfunc.argsType2CStrList()+");\n"); break; case EXPORT_GL_DISPATCH_VAR: System.out.println("\t"+ cfunc.funcSpec.getCTypeString()+ " (CALLBACK * disp__"+ cfunc.funcSpec.identifier + " )("+ cfunc.argsType2CStrList()+") = NULL;\n"); break; case EXPORT_GL_DISPATCH_GET: System.out.println("\tdisp__"+cfunc.funcSpec.identifier+ " = ("+ cfunc.funcSpec.getCTypeString()+ " (CALLBACK *)("+ cfunc.argsType2CStrList()+"))"+ "\n\t GET_GL_PROCADDRESS (\""+ cfunc.funcSpec.identifier+"\");\n"); break; case EXPORT_MSJDIRECT_JAVA : System.out.println(cfunc.toMsJDirectCode(dllname)); break; } } } CFuncDeclaration FunctionDefinition() : { CFuncDeclaration cfunc= new CFuncDeclaration(); } { [ LOOKAHEAD(DeclarationSpecifiers(null)) DeclarationSpecifiers(cfunc)] Declarator(cfunc) [ DeclarationList(cfunc) ] CompoundStatement() { return cfunc; } } CFuncDeclaration Declaration(CFuncDeclaration cfunc) : { if(cfunc==null) cfunc = new CFuncDeclaration(); } { DeclarationSpecifiers(cfunc) [ InitDeclaratorList(cfunc) ] ";" { cSrc += ";\n"; return cfunc; } } void DeclarationList(CFuncDeclaration cfunc) : {} { ( LOOKAHEAD(Declaration(null)) Declaration(cfunc) )+ } void DeclarationSpecifiers(CFuncDeclaration cfunc) : { CFuncVariable cfvar=null; if(cfunc!=null) cfvar=cfunc.getLastIncompleteVar(); } { StorageClassSpecifier(cfunc) [ LOOKAHEAD(DeclarationSpecifiers(null)) DeclarationSpecifiers(cfunc) ] | cfvar=TypeSpecifier(cfvar) { if(cfunc!=null) { cfunc.setWorkingVar(cfvar); } } [ LOOKAHEAD(DeclarationSpecifiers(null)) DeclarationSpecifiers(cfunc) ] | cfvar=TypeQualifier(cfvar) { if(cfunc!=null) { cfunc.setWorkingVar(cfvar); } } [ LOOKAHEAD(DeclarationSpecifiers(null)) DeclarationSpecifiers(cfunc) ] } void StorageClassSpecifier(CFuncDeclaration cfunc) : { Token t; } { ( t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; }| t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; }| t= { cSrc += t.image+" "; } { typedefParsingStack.push(Boolean.TRUE); } ) } CFuncVariable TypeSpecifier(CFuncVariable cfvar) : { String typeJava; Token t=null; boolean isVoid=false; } { ( ( ( t= { typeJava=t.image; isVoid=true; cSrc += t.image+" "; } | t= { typeJava="byte"; cSrc += t.image+" "; } | t= { typeJava=t.image; cSrc += t.image+" "; } | t= { typeJava=t.image; cSrc += t.image+" "; } | t= { typeJava=t.image; cSrc += t.image+" "; } | t= { typeJava=t.image; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava=t.image; cSrc += t.image+" "; } ) { if(cfvar==null) cfvar = new CFuncVariable(usePointerHolderCast); cfvar.typeC = t.image; cfvar.typeJava = typeJava; cfvar.isVoid = isVoid; return cfvar; } | cfvar=TypeSpecifierGL(cfvar) { return cfvar; } ) | StructOrUnionSpecifier() | EnumSpecifier() | LOOKAHEAD( { isType(getToken(1).image) } ) TypedefName() ) { return null; } } CFuncVariable TypeSpecifierGL(CFuncVariable cfvar) : { String typeJava; Token t=null; boolean isVoid=false; } { ( t= { typeJava="void"; cSrc += t.image+" "; isVoid=true; } | t= { typeJava="byte"; cSrc += t.image+" "; } | t= { typeJava="short"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="float"; cSrc += t.image+" "; } | t= { typeJava="float"; cSrc += t.image+" "; } | t= { typeJava="double"; cSrc += t.image+" "; } | t= { typeJava="double"; cSrc += t.image+" "; } | t= { typeJava="byte"; cSrc += t.image+" "; } | t= { typeJava="boolean"; cSrc += t.image+" "; } | t= { typeJava="short"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="int"; cSrc += t.image+" "; } | t= { typeJava="long"; cSrc += t.image+" "; } | t= { typeJava="long"; cSrc += t.image+" "; } | t= { typeJava="long"; cSrc += t.image+" "; } | t= { typeJava="long"; cSrc += t.image+" "; } ) { if(cfvar==null) cfvar = new CFuncVariable(usePointerHolderCast); cfvar.typeC = t.image; cfvar.typeJava = typeJava; cfvar.isVoid = isVoid; return cfvar; } } CFuncVariable TypeQualifier(CFuncVariable cfvar) : { Token t; } { ( t= { cSrc += t.image+" "; if(cfvar==null) cfvar = new CFuncVariable(usePointerHolderCast); cfvar.isConst=true; return cfvar; } | t= { cSrc += t.image+" "; return cfvar; } ) } void StructOrUnionSpecifier() : { Token t; } { { typedefParsingStack.push(Boolean.FALSE); } StructOrUnion() ( LOOKAHEAD(3) [ t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*StrucOrUnionSpec*/"; } ] "{" { cSrc += "{\n"; } StructDeclarationList() "}" { cSrc += "}\n"; } | t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*StrucOrUnionSpec2*/"; } ) { typedefParsingStack.pop(); } } void StructOrUnion() : { Token t; } { ( t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; } ) } void StructDeclarationList() : {} { (StructDeclaration())+ } void InitDeclaratorList(CFuncDeclaration cfunc) : {} { InitDeclarator(cfunc) ( "," { cSrc += ", "; } InitDeclarator(cfunc))* { // Finished with a typedefDeclaration?? if(!(typedefParsingStack.empty()) && ((Boolean)typedefParsingStack.peek()).booleanValue()){ typedefParsingStack.pop(); } } } void InitDeclarator(CFuncDeclaration cfunc) : {} { Declarator(cfunc) [ "=" { cSrc += "= "; } Initializer() ] } void StructDeclaration() : {} { SpecifierQualifierList(null) StructDeclaratorList() ";" { cSrc += ";\n"; } } CFuncVariable SpecifierQualifierList(CFuncVariable cfvar) : {} { cfvar=TypeSpecifier(cfvar) [ LOOKAHEAD(SpecifierQualifierList(null)) SpecifierQualifierList(cfvar) ] { return cfvar; } | cfvar=TypeQualifier(cfvar) [ LOOKAHEAD(SpecifierQualifierList(null)) SpecifierQualifierList(cfvar) ] { return cfvar; } } void StructDeclaratorList() : {} { StructDeclarator() ( "," { cSrc += ", "; } StructDeclarator() )* } void StructDeclarator() : {} { ( LOOKAHEAD(3) Declarator(null) | [ Declarator(null) ] ":" { cSrc += ": "; } ConstantExpression() ) } void EnumSpecifier() : { Token t; } { t= { cSrc += t.image+" "; } ( LOOKAHEAD(3) [ t= { cSrc += t.image+" "; } ] "{" { cSrc += "{\n"; } EnumeratorList() "}" { cSrc += "}\n"; } | t= { cSrc += t.image+" "; } ) } void EnumeratorList() : { lastEnumValue=0; } { Enumerator() ("," { cSrc += ",\n"; } Enumerator())* { cSrc += "\n\t;\n"; } } void Enumerator() : { Token t; int startIdx; } { t= { cSrc += "\t"+t.image+" "; startIdx=-1; } [ "=" { cSrc += "= "; startIdx=cSrc.length(); } ConstantExpression() ] { System.out.print("\tpublic static final int "+t.image+"\t= "); if(startIdx>=0) { String valStr = cSrc.substring(startIdx, cSrc.length()).trim(); System.out.print(valStr); int val = 0; try { val=Integer.decode(valStr).intValue(); lastEnumValue=val; } catch (Exception ex) { System.err.println("Error while decoding for <"+ t.image+">: <"+valStr+">"); lastEnumValue++; } } else { lastEnumValue++; System.out.print(lastEnumValue); } System.out.println(";"); } } void Declarator(CFuncDeclaration cfunc) : { CFuncVariable cfvar=null; } { { if(cfunc!=null) cfvar = cfunc.getWorkingVar(); } [ Pointer(cfvar) ] DirectDeclarator(cfunc) } void DirectDeclarator(CFuncDeclaration cfunc) : { Token t; } { ( t = { cSrc+=t.image+" "; if(syntaxVerbose) cSrc += "/*DirectDecl1*/ "; if(!(typedefParsingStack.empty()) && ((Boolean)typedefParsingStack.peek()).booleanValue()) { addType(t.image); } if(cfunc==null) return; // // Complete the variable declarations in the holder ! // CFuncVariable cfvar = cfunc.getWorkingVar(); cfvar.identifier=t.image; cfvar.complete=true; } | "(" { cSrc += "( "; if(syntaxVerbose) cSrc += "/*DirectDecl2*/ "; } Declarator(cfunc) ")" { cSrc += ") "; } ) ( "[" { cSrc += "[ "; } [ ConstantExpression() ] "]" { cSrc += "] "; if(cfunc!=null) { CFuncVariable cfvar = (CFuncVariable) cfunc.argList.elementAt(cfunc.argList.size()-1); cfvar.arrayNumber++; } } | LOOKAHEAD(3) "(" { cSrc += "( "; if(syntaxVerbose) cSrc += "/*DirectDecl3*/ "; } [ ParameterTypeList(cfunc) ] ")" { cSrc += ") "; } | "(" { cSrc += "( "; if(syntaxVerbose) cSrc += "/*DirectDecl4*/ "; } IdentifierList() ")" { cSrc += ") "; } )* } void Pointer(CFuncVariable cfvar) : {} { "*" { cSrc += "* "; if(cfvar!=null) { if(cfvar.typeC!=null) { /** * No Pointer - These GLU Types are allready * "long" values for java -> pointer */ if(cfvar.typeC.equals("GLUquadric") || cfvar.typeC.equals("GLUnurbs") || cfvar.typeC.equals("GLUtesselator") || cfvar.typeC.equals("GLUtriangulator") ) { cfvar.isGLUPtrObject=true; return; } else if(cfvar.typeC.equals("char") && cfvar.isConst) { cfvar.typeJava = "String"; } } cfvar.arrayNumber++; } } [ TypeQualifierList(null) ] [ Pointer(cfvar) ] } void TypeQualifierList(CFuncVariable cfvar) : {} { (TypeQualifier(cfvar))+ } void ParameterTypeList(CFuncDeclaration cfunc) : {} { ParameterList(cfunc) ["," { cSrc += ", "; } "..." { cSrc += "..."; } ] } void ParameterList(CFuncDeclaration cfunc) : {} { ParameterDeclaration(cfunc) (LOOKAHEAD(2) "," { cSrc += ", "; } ParameterDeclaration(cfunc))* } void ParameterDeclaration(CFuncDeclaration cfunc) : {} { DeclarationSpecifiers(cfunc) ( LOOKAHEAD(Declarator(null)) Declarator(cfunc) | [ AbstractDeclarator(cfunc) ] ) { if(cfunc!=null) { CFuncVariable cfvar = cfunc.getLastIncompleteVar(); if(cfvar!=null) { /** * We may must squash the "void" Argument * E.g. void function(void) ! */ if(cfvar.isVoid && exportMode != EXPORT_GL_DISPATCH_DECL && exportMode != EXPORT_GL_DISPATCH_VAR && exportMode != EXPORT_GL_DISPATCH_GET && exportMode != EXPORT_MSJDIRECT_JAVA ) { cfunc.argList.removeElementAt( cfunc.argList.size()-1); return; } /** * We have a regular argument, * so we must add an instance name here ... */ if(cfvar.isVoid) cfvar.identifier=" "; else cfvar.identifier="arg"+(cfunc.argList.size()-1); cfvar.complete=true; } } } } /** * * J2C Declaration Changes END (JAU) * */ void IdentifierList() : { Token t; } { t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*IdentifierList*/ "; } ("," { cSrc += ", "; } t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*IdentifierList2*/ "; } )* } void Initializer() : {} { ( AssignmentExpression() | "{" { cSrc += "{\n"; } InitializerList() ["," { cSrc += ", "; } ] "}" { cSrc += "}\n"; } ) } void InitializerList() : {} { Initializer() (LOOKAHEAD(2) "," { cSrc += ", "; } Initializer())* } void TypeName() : {} { SpecifierQualifierList(null) [ AbstractDeclarator(null) ] } void AbstractDeclarator(CFuncDeclaration cfunc) : { CFuncVariable cfvar=null; } { { if(cfunc!=null) cfvar = cfunc.getWorkingVar(); } ( LOOKAHEAD(3) Pointer(cfvar) | [Pointer(cfvar)] DirectAbstractDeclarator() ) { if(syntaxVerbose) cSrc += "/*AbstractDecl1*/ "; if(cfvar==null) return; // // Complete the variable declarations in the holder ! // cfvar.identifier="arg"+cfunc.getWorkingVarIdx(); cfvar.complete=true; } } void DirectAbstractDeclarator() : {} { ( LOOKAHEAD(2) "(" { cSrc += "( "; } AbstractDeclarator(null) ")" { cSrc += ") "; } | "[" { cSrc += "[ "; } [ConstantExpression()] "]" { cSrc += "] "; } | "(" { cSrc += "( "; } [ParameterTypeList(null)] ")" { cSrc += ") "; } ) ( "[" { cSrc += "[ "; } [ ConstantExpression() ] "]" { cSrc += "] "; } | "(" { cSrc += "( "; } [ ParameterTypeList(null) ] ")" { cSrc += ") "; } )* } void TypedefName() : { Token t; } { t= { cSrc += t.image+" /*TypedefName*/"; } } void Statement() : {} { ( LOOKAHEAD(2) LabeledStatement() | ExpressionStatement() | CompoundStatement() | SelectionStatement() | IterationStatement() | JumpStatement() ) } void LabeledStatement() : { Token t; } { ( t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*LabeledStatement*/ "; } ":" { cSrc += ": "; } Statement() | t= { cSrc += t.image+" "; } ConstantExpression() ":"{ cSrc += ": "; } Statement() | t= { cSrc += t.image+" "; } ":"{ cSrc += ": "; } Statement() ) } void ExpressionStatement() : {} { [ Expression() ] ";"{ cSrc += ";\n"; } } void CompoundStatement() : {} { "{" { cSrc += "{\n"; } [ LOOKAHEAD(DeclarationList(null)) DeclarationList(null) ] [ StatementList() ] "}"{ cSrc += "}\n"; } } void StatementList() : {} { (Statement())+ } void SelectionStatement() : { Token t; } { ( t= { cSrc += t.image+" "; } "(" { cSrc += "( "; } Expression() ")" { cSrc += ")\n"; } Statement() [ LOOKAHEAD(2) t= { cSrc += t.image+" "; } Statement() ] | t= { cSrc += t.image+" "; } "(" { cSrc += "( "; } Expression() ")" { cSrc += ")\n"; } Statement() ) } void IterationStatement() : { Token t; } { ( t= { cSrc += t.image+" "; } "(" { cSrc += "( "; } Expression() ")" { cSrc += ")\n"; } Statement() | t= { cSrc += t.image+"\n"; } Statement() t= { cSrc += t.image+" "; } "(" { cSrc += "( "; } Expression() ")" ";" { cSrc += ");\n"; } | t= { cSrc += t.image+" "; } "(" { cSrc += "( "; } [ Expression() ] ";" { cSrc += "; "; } [ Expression() ] ";" { cSrc += "; "; } [ Expression() ] ")" { cSrc += ")\n"; } Statement() ) } void JumpStatement() : { Token t; } { ( t= { cSrc += t.image+" "; } t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*JumpStat*/ "; } ";" { cSrc += ";\n"; } | t= { cSrc += t.image+" "; } ";" { cSrc += ";\n"; } | t= { cSrc += t.image+" "; } ";" { cSrc += ";\n"; } | t= { cSrc += t.image+" "; } [ Expression() ] ";" { cSrc += ";\n"; } ) } void Expression() : {} { AssignmentExpression() ( "," { cSrc += ", "; } AssignmentExpression() )* } void AssignmentExpression() : {} { LOOKAHEAD(UnaryExpression() AssignmentOperator()) UnaryExpression() AssignmentOperator() AssignmentExpression() | LOOKAHEAD(3) ConditionalExpression() } void AssignmentOperator() : {} { ( "=" { cSrc += "= "; } | "*=" { cSrc += "*= "; } | "/=" { cSrc += "/= "; } | "%=" { cSrc += "%= "; } | "+=" { cSrc += "+= "; } | "-=" { cSrc += "-= "; } | "<<=" { cSrc += "<<= "; } | ">>=" { cSrc += ">>= "; } | "&=" { cSrc += "&= "; } | "^=" { cSrc += "^= "; } | "|=" { cSrc += "|= "; } ) } void ConditionalExpression() : {} { LogicalORExpression() [ "?" { cSrc += "? "; } Expression() ":" { cSrc += ": "; } ConditionalExpression() ] } void ConstantExpression() : {} { ConditionalExpression() } void LogicalORExpression() : {} { LogicalANDExpression() [ "||" { cSrc += "|| "; } LogicalORExpression() ] } void LogicalANDExpression() : {} { InclusiveORExpression() [ "&&" { cSrc += "&& "; } LogicalANDExpression() ] } void InclusiveORExpression() : {} { ExclusiveORExpression() [ "|" { cSrc += "| "; } InclusiveORExpression() ] } void ExclusiveORExpression() : {} { ANDExpression() [ "^" { cSrc += "^ "; } ExclusiveORExpression() ] } void ANDExpression() : {} { EqualityExpression() [ "&" { cSrc += "& "; } ANDExpression() ] } void EqualityExpression() : {} { RelationalExpression() [ ( "==" { cSrc += "== "; } | "!=" { cSrc += "!= "; } ) EqualityExpression() ] } void RelationalExpression() : {} { ShiftExpression() [ ( "<" { cSrc += "< "; } | ">" { cSrc += "> "; } | "<=" { cSrc += "<= "; } | ">=" { cSrc += ">= "; } ) RelationalExpression() ] } void ShiftExpression() : {} { AdditiveExpression() [ ( "<<" { cSrc += "<< "; } | ">>" { cSrc += ">> "; } ) ShiftExpression() ] } void AdditiveExpression() : {} { MultiplicativeExpression() [ ( "+" { cSrc += "+ "; } | "-" { cSrc += "- "; } ) AdditiveExpression() ] } void MultiplicativeExpression() : {} { CastExpression() [ ( "*" { cSrc += "* "; } | "/" { cSrc += "/ "; } | "%" { cSrc += "% "; } ) MultiplicativeExpression() ] } void CastExpression() : { String help1= new String(); String help2= new String(); } { ( LOOKAHEAD( "(" TypeName(help1) ")" CastExpression(help2) ) { cSrc += "( "+help1+") "+help2; } "(" { cSrc += "( "; } TypeName() ")" { cSrc += ") "; } CastExpression() | UnaryExpression() ) } void UnaryExpression() : { Token t; } { ( LOOKAHEAD(3) PostfixExpression() | "++" { cSrc += "++ "; } UnaryExpression() | "--" { cSrc += "-- "; } UnaryExpression() | UnaryOperator() CastExpression() | t= { cSrc += t.image+" "; } ( LOOKAHEAD(UnaryExpression() ) UnaryExpression() | "(" { cSrc += "( "; } TypeName() ")" { cSrc += ") "; } ) ) } void UnaryOperator() : {} { ( "&" { cSrc += "& "; } | "*" { cSrc += "* "; } | "+" { cSrc += "+ "; } | "-" { cSrc += "- "; } | "~" { cSrc += "~ "; } | "!" { cSrc += "! "; } ) } void PostfixExpression() : { Token t; } { PrimaryExpression() ( "[" { cSrc += "[ "; } Expression() "]" { cSrc += "] "; } | "(" { cSrc += "( "; } [ LOOKAHEAD(ArgumentExpressionList() ) ArgumentExpressionList() ] ")" { cSrc += ") "; } | "." { cSrc += ". "; } t= { cSrc += t.image+" "; } | "->" { cSrc += "-> "; } t= { cSrc += t.image+" "; } | "++" { cSrc += "++ "; } | "--" { cSrc += "-- "; } )* } void PrimaryExpression() : { Token t; } { ( t= { cSrc += t.image+" "; if(syntaxVerbose) cSrc += "/*PrimaryExpr*/ "; } | Constant() | "(" { cSrc += "( "; } Expression() ")" { cSrc += ") "; } ) } void ArgumentExpressionList() : { } { AssignmentExpression() ( "," { cSrc += ", "; } AssignmentExpression() )* } void Constant() : { Token t; } { t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; } | t= { cSrc += t.image+" "; } }