From d30a3ea54e26978d6ff199cba0fd79c5c0cef483 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 25 Mar 2015 12:45:41 +0100 Subject: Bug 1149: Fix parsing of hexadecimal w/ binary exponent floats in regexp-constant and java-parser. (Due to PCPP -> JCPP) Lack of parsing binary exponent floats is exposed due to using JCPP and correct constant-definitions. - JavaParser.g: - Add support for hexadecimal w/ binary exponent floats - TAB -> 4 spaces - ConstantDefinition.java: - Add RegExp 'fpRegexp', patternDecimalNumber: decimal number w/ support for hexadecimal w/ binary exponent floats. - isDecimalNumber(..): Use patternDecimalNumber instead of try-and-error (NumberFormatException) - patternCPPOperand: exclude patternDecimalNumber! - JavaEmitter.java: - Respect explicit suffix [dD] for double type. - Drop floating point suffixes [fF] - Test: Added tests for hexadecimal w/ binary exponent floats --- make/scripts/runtest.sh | 4 +- src/antlr/com/jogamp/gluegen/jgram/JavaParser.g | 1509 ++++++++++---------- .../com/jogamp/gluegen/ConstantDefinition.java | 121 +- src/java/com/jogamp/gluegen/JavaEmitter.java | 9 +- .../gluegen/test/junit/generation/BaseClass.java | 34 +- .../jogamp/gluegen/test/junit/generation/test1.h | 16 + 6 files changed, 904 insertions(+), 789 deletions(-) diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh index 0837c42..16d08aa 100755 --- a/make/scripts/runtest.sh +++ b/make/scripts/runtest.sh @@ -138,10 +138,10 @@ function onetest() { #onetest com.jogamp.gluegen.jcpp.IncludeAbsoluteTest 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.jcpp.CppReaderTest 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.jcpp.TokenPastingWhitespaceTest 2>&1 | tee -a $LOG -onetest com.jogamp.gluegen.jcpp.PreprocessorTest 2>&1 | tee -a $LOG +#onetest com.jogamp.gluegen.jcpp.PreprocessorTest 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG -#onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG +onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.test.junit.generation.Test1p2LoadJNIAndImplLib 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.test.junit.structgen.TestStructGen01 2>&1 | tee -a $LOG #onetest com.jogamp.gluegen.test.junit.structgen.TestStructGen02 2>&1 | tee -a $LOG diff --git a/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g b/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g index f67579e..1c06bfd 100644 --- a/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g +++ b/src/antlr/com/jogamp/gluegen/jgram/JavaParser.g @@ -8,105 +8,105 @@ * Run 'java Main ' * * Contributing authors: - * John Mitchell johnm@non.net - * Terence Parr parrt@magelang.com - * John Lilley jlilley@empathy.com - * Scott Stanchfield thetick@magelang.com - * Markus Mohnen mohnen@informatik.rwth-aachen.de + * John Mitchell johnm@non.net + * Terence Parr parrt@magelang.com + * John Lilley jlilley@empathy.com + * Scott Stanchfield thetick@magelang.com + * Markus Mohnen mohnen@informatik.rwth-aachen.de * Peter Williams pete.williams@sun.com * Allan Jacobs Allan.Jacobs@eng.sun.com * Steve Messick messick@redhills.com - * John Pybus john@pybus.org + * John Pybus john@pybus.org * * Version 1.00 December 9, 1997 -- initial release * Version 1.01 December 10, 1997 - * fixed bug in octal def (0..7 not 0..8) + * fixed bug in octal def (0..7 not 0..8) * Version 1.10 August 1998 (parrt) - * added tree construction - * fixed definition of WS,comments for mac,pc,unix newlines - * added unary plus + * added tree construction + * fixed definition of WS,comments for mac,pc,unix newlines + * added unary plus * Version 1.11 (Nov 20, 1998) - * Added "shutup" option to turn off last ambig warning. - * Fixed inner class def to allow named class defs as statements - * synchronized requires compound not simple statement - * add [] after builtInType DOT class in primaryExpression - * "const" is reserved but not valid..removed from modifiers + * Added "shutup" option to turn off last ambig warning. + * Fixed inner class def to allow named class defs as statements + * synchronized requires compound not simple statement + * add [] after builtInType DOT class in primaryExpression + * "const" is reserved but not valid..removed from modifiers * Version 1.12 (Feb 2, 1999) - * Changed LITERAL_xxx to xxx in tree grammar. - * Updated java.g to use tokens {...} now for 2.6.0 (new feature). + * Changed LITERAL_xxx to xxx in tree grammar. + * Updated java.g to use tokens {...} now for 2.6.0 (new feature). * * Version 1.13 (Apr 23, 1999) - * Didn't have (stat)? for else clause in tree parser. - * Didn't gen ASTs for interface extends. Updated tree parser too. - * Updated to 2.6.0. + * Didn't have (stat)? for else clause in tree parser. + * Didn't gen ASTs for interface extends. Updated tree parser too. + * Updated to 2.6.0. * Version 1.14 (Jun 20, 1999) - * Allowed final/abstract on local classes. - * Removed local interfaces from methods - * Put instanceof precedence where it belongs...in relationalExpr - * It also had expr not type as arg; fixed it. - * Missing ! on SEMI in classBlock - * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus). - * fixed: didn't like Object[].class in parser or tree parser + * Allowed final/abstract on local classes. + * Removed local interfaces from methods + * Put instanceof precedence where it belongs...in relationalExpr + * It also had expr not type as arg; fixed it. + * Missing ! on SEMI in classBlock + * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus). + * fixed: didn't like Object[].class in parser or tree parser * Version 1.15 (Jun 26, 1999) - * Screwed up rule with instanceof in it. :( Fixed. - * Tree parser didn't like (expr).something; fixed. - * Allowed multiple inheritance in tree grammar. oops. + * Screwed up rule with instanceof in it. :( Fixed. + * Tree parser didn't like (expr).something; fixed. + * Allowed multiple inheritance in tree grammar. oops. * Version 1.16 (August 22, 1999) - * Extending an interface built a wacky tree: had extra EXTENDS. - * Tree grammar didn't allow multiple superinterfaces. - * Tree grammar didn't allow empty var initializer: {} + * Extending an interface built a wacky tree: had extra EXTENDS. + * Tree grammar didn't allow multiple superinterfaces. + * Tree grammar didn't allow empty var initializer: {} * Version 1.17 (October 12, 1999) - * ESC lexer rule allowed 399 max not 377 max. - * java.tree.g didn't handle the expression of synchronized - * statements. + * ESC lexer rule allowed 399 max not 377 max. + * java.tree.g didn't handle the expression of synchronized + * statements. * Version 1.18 (August 12, 2001) - * Terence updated to Java 2 Version 1.3 by - * observing/combining work of Allan Jacobs and Steve - * Messick. Handles 1.3 src. Summary: - * o primary didn't include boolean.class kind of thing - * o constructor calls parsed explicitly now: - * see explicitConstructorInvocation - * o add strictfp modifier - * o missing objBlock after new expression in tree grammar - * o merged local class definition alternatives, moved after declaration - * o fixed problem with ClassName.super.field - * o reordered some alternatives to make things more efficient - * o long and double constants were not differentiated from int/float - * o whitespace rule was inefficient: matched only one char - * o add an examples directory with some nasty 1.3 cases - * o made Main.java use buffered IO and a Reader for Unicode support - * o supports UNICODE? - * Using Unicode charVocabulay makes code file big, but only - * in the bitsets at the end. I need to make ANTLR generate - * unicode bitsets more efficiently. + * Terence updated to Java 2 Version 1.3 by + * observing/combining work of Allan Jacobs and Steve + * Messick. Handles 1.3 src. Summary: + * o primary didn't include boolean.class kind of thing + * o constructor calls parsed explicitly now: + * see explicitConstructorInvocation + * o add strictfp modifier + * o missing objBlock after new expression in tree grammar + * o merged local class definition alternatives, moved after declaration + * o fixed problem with ClassName.super.field + * o reordered some alternatives to make things more efficient + * o long and double constants were not differentiated from int/float + * o whitespace rule was inefficient: matched only one char + * o add an examples directory with some nasty 1.3 cases + * o made Main.java use buffered IO and a Reader for Unicode support + * o supports UNICODE? + * Using Unicode charVocabulay makes code file big, but only + * in the bitsets at the end. I need to make ANTLR generate + * unicode bitsets more efficiently. * Version 1.19 (April 25, 2002) - * Terence added in nice fixes by John Pybus concerning floating - * constants and problems with super() calls. John did a nice - * reorg of the primary/postfix expression stuff to read better - * and makes f.g.super() parse properly (it was METHOD_CALL not - * a SUPER_CTOR_CALL). Also: + * Terence added in nice fixes by John Pybus concerning floating + * constants and problems with super() calls. John did a nice + * reorg of the primary/postfix expression stuff to read better + * and makes f.g.super() parse properly (it was METHOD_CALL not + * a SUPER_CTOR_CALL). Also: * - * o "finally" clause was a root...made it a child of "try" - * o Added stuff for asserts too for Java 1.4, but *commented out* - * as it is not backward compatible. + * o "finally" clause was a root...made it a child of "try" + * o Added stuff for asserts too for Java 1.4, but *commented out* + * as it is not backward compatible. * * Version 1.20 (October 27, 2002) * * Terence ended up reorging John Pybus' stuff to * remove some nondeterminisms and some syntactic predicates. * Note that the grammar is stricter now; e.g., this(...) must - * be the first statement. + * be the first statement. * * Trinary ?: operator wasn't working as array name: * (isBig ? bigDigits : digits)[i]; * * Checked parser/tree parser on source for * Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4, - * and the 110k-line jGuru server source. + * and the 110k-line jGuru server source. * * Version 1.21 (October 17, 2003) - * Fixed lots of problems including: - * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g + * Fixed lots of problems including: + * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g * He found a problem/fix with floating point that start with 0 * Ray also fixed problem that (int.class) was not recognized. * Thorsten van Ellen noticed that \n are allowed incorrectly in strings. @@ -129,24 +129,24 @@ header { class JavaParser extends Parser; options { - k = 2; // two token lookahead - exportVocab=Java; // Call its vocabulary "Java" - codeGenMakeSwitchThreshold = 2; // Some optimizations - codeGenBitsetTestThreshold = 3; - defaultErrorHandler = false; // Don't generate parser error handlers - buildAST = true; - //buildAST = false; + k = 2; // two token lookahead + exportVocab=Java; // Call its vocabulary "Java" + codeGenMakeSwitchThreshold = 2; // Some optimizations + codeGenBitsetTestThreshold = 3; + defaultErrorHandler = false; // Don't generate parser error handlers + buildAST = true; + //buildAST = false; } tokens { - BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF; - INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF; - PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE; - PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP; - POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT; - IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION; - FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract"; - STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL; + BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF; + INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF; + PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE; + PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP; + POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT; + IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION; + FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract"; + STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL; } { @@ -181,250 +181,250 @@ tokens { // Compilation Unit: In Java, this is a single file. This is the start // rule for this parser compilationUnit - : // A compilation unit starts with an optional package definition - ( packageDefinition - | /* nothing */ - ) + : // A compilation unit starts with an optional package definition + ( packageDefinition + | /* nothing */ + ) - // Next we have a series of zero or more import statements - ( importDefinition )* + // Next we have a series of zero or more import statements + ( importDefinition )* - // Wrapping things up with any number of class or interface - // definitions - ( typeDefinition )* + // Wrapping things up with any number of class or interface + // definitions + ( typeDefinition )* - EOF! - ; + EOF! + ; // Package statement: "package" followed by an identifier. packageDefinition - options {defaultErrorHandler = true;} // let ANTLR handle errors - : p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI! - ; + options {defaultErrorHandler = true;} // let ANTLR handle errors + : p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI! + ; // Import statement: import followed by a package or class name importDefinition - options {defaultErrorHandler = true;} - : i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI! - ; + options {defaultErrorHandler = true;} + : i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI! + ; // A type definition in a file is either a class or interface definition. typeDefinition - options {defaultErrorHandler = true;} - : m:modifiers! - ( classDefinition[#m] - | interfaceDefinition[#m] - ) - | SEMI! - ; + options {defaultErrorHandler = true;} + : m:modifiers! + ( classDefinition[#m] + | interfaceDefinition[#m] + ) + | SEMI! + ; /** A declaration is the creation of a reference or primitive-type variable * Create a separate Type/Var tree for each var in the var list. */ declaration! - : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t] - {#declaration = #v;} - ; + : m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t] + {#declaration = #v;} + ; // A type specification is a type name with possible brackets afterwards // (which would make it an array type). typeSpec[boolean addImagNode] - : classTypeSpec[addImagNode] - | builtInTypeSpec[addImagNode] - ; + : classTypeSpec[addImagNode] + | builtInTypeSpec[addImagNode] + ; // A class type specification is a class type with possible brackets afterwards // (which would make it an array type). classTypeSpec[boolean addImagNode] - : identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - { - if ( addImagNode ) { - #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec); - } - } - ; + : identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* + { + if ( addImagNode ) { + #classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec); + } + } + ; // A builtin type specification is a builtin type with possible brackets // afterwards (which would make it an array type). builtInTypeSpec[boolean addImagNode] - : builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - { - if ( addImagNode ) { - #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec); - } - } - ; + : builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* + { + if ( addImagNode ) { + #builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec); + } + } + ; // A type name. which is either a (possibly qualified) class name or // a primitive (builtin) type type - : identifier - | builtInType - ; + : identifier + | builtInType + ; // The primitive types. builtInType - : "void" - | "boolean" - | "byte" - | "char" - | "short" - | "int" - | "float" - | "long" - | "double" - ; + : "void" + | "boolean" + | "byte" + | "char" + | "short" + | "int" + | "float" + | "long" + | "double" + ; // A (possibly-qualified) java identifier. We start with the first IDENT // and expand its name by adding dots and following IDENTS identifier - : IDENT ( DOT^ IDENT )* - ; + : IDENT ( DOT^ IDENT )* + ; identifierStar - : IDENT - ( DOT^ IDENT )* - ( DOT^ STAR )? - ; + : IDENT + ( DOT^ IDENT )* + ( DOT^ STAR )? + ; // A list of zero or more modifiers. We could have used (modifier)* in // place of a call to modifiers, but I thought it was a good idea to keep // this rule separate so they can easily be collected in a Vector if // someone so desires modifiers - : ( modifier )* - {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);} - ; + : ( modifier )* + {#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);} + ; // modifiers for Java classes, interfaces, class/instance vars and methods modifier - : "private" - | "public" - | "protected" - | "static" - | "transient" - | "final" - | "abstract" - | "native" - | "threadsafe" - | "synchronized" -// | "const" // reserved word, but not valid - | "volatile" - | "strictfp" - ; + : "private" + | "public" + | "protected" + | "static" + | "transient" + | "final" + | "abstract" + | "native" + | "threadsafe" + | "synchronized" +// | "const" // reserved word, but not valid + | "volatile" + | "strictfp" + ; // Definition of a Java class classDefinition![AST modifiers] - : "class" IDENT - // it _might_ have a superclass... - sc:superClassClause - // it might implement some interfaces... - ic:implementsClause - // now parse the body of the class - cb:classBlock - {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"], - modifiers,IDENT,sc,ic,cb);} - ; + : "class" IDENT + // it _might_ have a superclass... + sc:superClassClause + // it might implement some interfaces... + ic:implementsClause + // now parse the body of the class + cb:classBlock + {#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"], + modifiers,IDENT,sc,ic,cb);} + ; superClassClause! - : ( "extends" id:identifier )? - {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);} - ; + : ( "extends" id:identifier )? + {#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);} + ; // Definition of a Java Interface interfaceDefinition![AST modifiers] - : "interface" IDENT - // it might extend some other interfaces - ie:interfaceExtends - // now parse the body of the interface (looks like a class...) - cb:classBlock - {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"], - modifiers,IDENT,ie,cb);} - ; + : "interface" IDENT + // it might extend some other interfaces + ie:interfaceExtends + // now parse the body of the interface (looks like a class...) + cb:classBlock + {#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"], + modifiers,IDENT,ie,cb);} + ; // This is the body of a class. You can have fields and extra semicolons, // That's about it (until you see what a field is...) classBlock - : LCURLY! { blockDepth++; } - ( field | SEMI! )* - RCURLY! { blockDepth--; } - {#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);} - ; + : LCURLY! { blockDepth++; } + ( field | SEMI! )* + RCURLY! { blockDepth--; } + {#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);} + ; // An interface can extend several other interfaces... interfaceExtends - : ( - e:"extends"! - identifier ( COMMA! identifier )* - )? - {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"], - #interfaceExtends);} - ; + : ( + e:"extends"! + identifier ( COMMA! identifier )* + )? + {#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"], + #interfaceExtends);} + ; // A class can implement several interfaces... implementsClause - : ( - i:"implements"! identifier ( COMMA! identifier )* - )? - {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"], - #implementsClause);} - ; + : ( + i:"implements"! identifier ( COMMA! identifier )* + )? + {#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"], + #implementsClause);} + ; // Now the various things that can be defined inside a class or interface... // Note that not all of these are really valid in an interface (constructors, // for example), and if this grammar were used for a compiler there would // need to be some semantic checks to make sure we're doing the right thing... field! - : // method, constructor, or variable declaration - mods:modifiers - ( h:ctorHead s:constructorBody // constructor - {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);} + : // method, constructor, or variable declaration + mods:modifiers + ( h:ctorHead s:constructorBody // constructor + {#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);} - | cd:classDefinition[#mods] // inner class - {#field = #cd;} + | cd:classDefinition[#mods] // inner class + {#field = #cd;} - | id:interfaceDefinition[#mods] // inner interface - {#field = #id;} + | id:interfaceDefinition[#mods] // inner interface + {#field = #id;} - | t:typeSpec[false] // method or variable declaration(s) - ( fn:IDENT // the name of the method + | t:typeSpec[false] // method or variable declaration(s) + ( fn:IDENT // the name of the method - // parse the formal parameter declarations. - LPAREN! param:parameterDeclarationList RPAREN! + // parse the formal parameter declarations. + LPAREN! param:parameterDeclarationList RPAREN! - rt:declaratorBrackets[#t] + rt:declaratorBrackets[#t] - // get the list of exceptions that this method is - // declared to throw - (tc:throwsClause)? + // get the list of exceptions that this method is + // declared to throw + (tc:throwsClause)? - ( s2:compoundStatement | SEMI ) - {#field = #(#[METHOD_DEF,"METHOD_DEF"], - mods, - #(#[TYPE,"TYPE"],rt), - fn, - param, - tc, - s2); + ( s2:compoundStatement | SEMI ) + {#field = #(#[METHOD_DEF,"METHOD_DEF"], + mods, + #(#[TYPE,"TYPE"],rt), + fn, + param, + tc, + s2); if(blockDepth==1) { functionNames.add(fn.getText()); } } - | v:variableDefinitions[#mods,#t] SEMI -// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);} - {#field = #v;} - ) - ) + | v:variableDefinitions[#mods,#t] SEMI +// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);} + {#field = #v;} + ) + ) // "static { ... }" class initializer - | "static" s3:compoundStatement - {#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);} + | "static" s3:compoundStatement + {#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);} // "{ ... }" instance initializer - | s4:compoundStatement - {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);} - ; + | s4:compoundStatement + {#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);} + ; constructorBody : lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; } @@ -436,108 +436,108 @@ constructorBody /** Catch obvious constructor calls, but not the expr.super(...) calls */ explicitConstructorInvocation : "this"! lp1:LPAREN^ argList RPAREN! SEMI! - {#lp1.setType(CTOR_CALL);} + {#lp1.setType(CTOR_CALL);} | "super"! lp2:LPAREN^ argList RPAREN! SEMI! - {#lp2.setType(SUPER_CTOR_CALL);} + {#lp2.setType(SUPER_CTOR_CALL);} ; variableDefinitions[AST mods, AST t] - : variableDeclarator[getASTFactory().dupTree(mods), - getASTFactory().dupTree(t)] - ( COMMA! - variableDeclarator[getASTFactory().dupTree(mods), - getASTFactory().dupTree(t)] - )* - ; + : variableDeclarator[getASTFactory().dupTree(mods), + getASTFactory().dupTree(t)] + ( COMMA! + variableDeclarator[getASTFactory().dupTree(mods), + getASTFactory().dupTree(t)] + )* + ; /** Declaration of a variable. This can be a class/instance variable, * or a local variable in a method * It can also include possible initialization. */ variableDeclarator![AST mods, AST t] - : id:IDENT d:declaratorBrackets[t] v:varInitializer - {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v); + : id:IDENT d:declaratorBrackets[t] v:varInitializer + {#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v); if(blockDepth==1) { enumNames.add(id.getText()); } } - ; + ; declaratorBrackets[AST typ] - : {#declaratorBrackets=typ;} - (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* - ; + : {#declaratorBrackets=typ;} + (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)* + ; varInitializer - : ( ASSIGN^ initializer )? - ; + : ( ASSIGN^ initializer )? + ; // This is an initializer used to set up an array. arrayInitializer - : lc:LCURLY^ {#lc.setType(ARRAY_INIT); blockDepth++; } - ( initializer - ( - // CONFLICT: does a COMMA after an initializer start a new - // initializer or start the option ',' at end? - // ANTLR generates proper code by matching - // the comma as soon as possible. - options { - warnWhenFollowAmbig = false; - } - : - COMMA! initializer - )* - (COMMA!)? - )? - RCURLY! { blockDepth--; } - ; + : lc:LCURLY^ {#lc.setType(ARRAY_INIT); blockDepth++; } + ( initializer + ( + // CONFLICT: does a COMMA after an initializer start a new + // initializer or start the option ',' at end? + // ANTLR generates proper code by matching + // the comma as soon as possible. + options { + warnWhenFollowAmbig = false; + } + : + COMMA! initializer + )* + (COMMA!)? + )? + RCURLY! { blockDepth--; } + ; // The two "things" that can initialize an array element are an expression // and another (nested) array initializer. initializer - : expression - | arrayInitializer - ; + : expression + | arrayInitializer + ; // This is the header of a method. It includes the name and parameters // for the method. // This also watches for a list of exception classes in a "throws" clause. ctorHead - : IDENT // the name of the method + : IDENT // the name of the method - // parse the formal parameter declarations. - LPAREN! parameterDeclarationList RPAREN! + // parse the formal parameter declarations. + LPAREN! parameterDeclarationList RPAREN! - // get the list of exceptions that this method is declared to throw - (throwsClause)? - ; + // get the list of exceptions that this method is declared to throw + (throwsClause)? + ; // This is a list of exception classes that the method is declared to throw throwsClause - : "throws"^ identifier ( COMMA! identifier )* - ; + : "throws"^ identifier ( COMMA! identifier )* + ; // A list of formal parameters parameterDeclarationList - : ( parameterDeclaration ( COMMA! parameterDeclaration )* )? - {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"], - #parameterDeclarationList);} - ; + : ( parameterDeclaration ( COMMA! parameterDeclaration )* )? + {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"], + #parameterDeclarationList);} + ; // A formal parameter. parameterDeclaration! - : pm:parameterModifier t:typeSpec[false] id:IDENT - pd:declaratorBrackets[#t] - {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"], - pm, #([TYPE,"TYPE"],pd), id);} - ; + : pm:parameterModifier t:typeSpec[false] id:IDENT + pd:declaratorBrackets[#t] + {#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"], + pm, #([TYPE,"TYPE"],pd), id);} + ; parameterModifier - : (f:"final")? - {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);} - ; + : (f:"final")? + {#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);} + ; // Compound statement. This is used in many contexts: // Inside a class definition prefixed with "static": @@ -549,151 +549,151 @@ parameterModifier // it starts a new scope for variable definitions compoundStatement - : lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; } - // include the (possibly-empty) list of statements - (statement)* - RCURLY! { blockDepth--; } - ; + : lc:LCURLY^ {#lc.setType(SLIST); blockDepth++; } + // include the (possibly-empty) list of statements + (statement)* + RCURLY! { blockDepth--; } + ; statement - // A list of statements in curly braces -- start a new scope! - : compoundStatement - - // declarations are ambiguous with "ID DOT" relative to expression - // statements. Must backtrack to be sure. Could use a semantic - // predicate to test symbol table to see what the type was coming - // up, but that's pretty hard without a symbol table ;) - | (declaration)=> declaration SEMI! - - // An expression statement. This could be a method call, - // assignment statement, or any other expression evaluated for - // side-effects. - | expression SEMI! - - // class definition - | m:modifiers! classDefinition[#m] - - // Attach a label to the front of a statement - | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement - - // If-else statement - | "if"^ LPAREN! expression RPAREN! statement - ( - // CONFLICT: the old "dangling-else" problem... - // ANTLR generates proper code matching - // as soon as possible. Hush warning. - options { - warnWhenFollowAmbig = false; - } - : - "else"! statement - )? - - // For statement - | "for"^ - LPAREN! - forInit SEMI! // initializer - forCond SEMI! // condition test - forIter // updater - RPAREN! - statement // statement to loop over - - // While statement - | "while"^ LPAREN! expression RPAREN! statement - - // do-while statement - | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI! - - // get out of a loop (or switch) - | "break"^ (IDENT)? SEMI! - - // do next iteration of a loop - | "continue"^ (IDENT)? SEMI! - - // Return an expression - | "return"^ (expression)? SEMI! - - // switch/case statement - | "switch"^ LPAREN! expression RPAREN! LCURLY! { blockDepth++; } - ( casesGroup )* - RCURLY! { blockDepth--; } - - // exception try-catch block - | tryBlock - - // throw an exception - | "throw"^ expression SEMI! - - // synchronize a statement - | "synchronized"^ LPAREN! expression RPAREN! compoundStatement - - // asserts (uncomment if you want 1.4 compatibility) - // | "assert"^ expression ( COLON! expression )? SEMI! - - // empty statement - | s:SEMI {#s.setType(EMPTY_STAT);} - ; + // A list of statements in curly braces -- start a new scope! + : compoundStatement + + // declarations are ambiguous with "ID DOT" relative to expression + // statements. Must backtrack to be sure. Could use a semantic + // predicate to test symbol table to see what the type was coming + // up, but that's pretty hard without a symbol table ;) + | (declaration)=> declaration SEMI! + + // An expression statement. This could be a method call, + // assignment statement, or any other expression evaluated for + // side-effects. + | expression SEMI! + + // class definition + | m:modifiers! classDefinition[#m] + + // Attach a label to the front of a statement + | IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement + + // If-else statement + | "if"^ LPAREN! expression RPAREN! statement + ( + // CONFLICT: the old "dangling-else" problem... + // ANTLR generates proper code matching + // as soon as possible. Hush warning. + options { + warnWhenFollowAmbig = false; + } + : + "else"! statement + )? + + // For statement + | "for"^ + LPAREN! + forInit SEMI! // initializer + forCond SEMI! // condition test + forIter // updater + RPAREN! + statement // statement to loop over + + // While statement + | "while"^ LPAREN! expression RPAREN! statement + + // do-while statement + | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI! + + // get out of a loop (or switch) + | "break"^ (IDENT)? SEMI! + + // do next iteration of a loop + | "continue"^ (IDENT)? SEMI! + + // Return an expression + | "return"^ (expression)? SEMI! + + // switch/case statement + | "switch"^ LPAREN! expression RPAREN! LCURLY! { blockDepth++; } + ( casesGroup )* + RCURLY! { blockDepth--; } + + // exception try-catch block + | tryBlock + + // throw an exception + | "throw"^ expression SEMI! + + // synchronize a statement + | "synchronized"^ LPAREN! expression RPAREN! compoundStatement + + // asserts (uncomment if you want 1.4 compatibility) + // | "assert"^ expression ( COLON! expression )? SEMI! + + // empty statement + | s:SEMI {#s.setType(EMPTY_STAT);} + ; casesGroup - : ( // CONFLICT: to which case group do the statements bind? - // ANTLR generates proper code: it groups the - // many "case"/"default" labels together then - // follows them with the statements - options { - greedy = true; - } - : - aCase - )+ - caseSList - {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);} - ; + : ( // CONFLICT: to which case group do the statements bind? + // ANTLR generates proper code: it groups the + // many "case"/"default" labels together then + // follows them with the statements + options { + greedy = true; + } + : + aCase + )+ + caseSList + {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);} + ; aCase - : ("case"^ expression | "default") COLON! - ; + : ("case"^ expression | "default") COLON! + ; caseSList - : (statement)* - {#caseSList = #(#[SLIST,"SLIST"],#caseSList);} - ; + : (statement)* + {#caseSList = #(#[SLIST,"SLIST"],#caseSList);} + ; // The initializer for a for loop forInit - // if it looks like a declaration, it is - : ( (declaration)=> declaration - // otherwise it could be an expression list... - | expressionList - )? - {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);} - ; + // if it looks like a declaration, it is + : ( (declaration)=> declaration + // otherwise it could be an expression list... + | expressionList + )? + {#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);} + ; forCond - : (expression)? - {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);} - ; + : (expression)? + {#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);} + ; forIter - : (expressionList)? - {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);} - ; + : (expressionList)? + {#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);} + ; // an exception handler try/catch block tryBlock - : "try"^ compoundStatement - (handler)* - ( finallyClause )? - ; + : "try"^ compoundStatement + (handler)* + ( finallyClause )? + ; finallyClause - : "finally"^ compoundStatement - ; + : "finally"^ compoundStatement + ; // an exception handler handler - : "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement - ; + : "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement + ; // expressions @@ -732,22 +732,22 @@ handler // the mother of all expressions expression - : assignmentExpression - {#expression = #(#[EXPR,"EXPR"],#expression);} - ; + : assignmentExpression + {#expression = #(#[EXPR,"EXPR"],#expression);} + ; // This is a list of expressions. expressionList - : expression (COMMA! expression)* - {#expressionList = #(#[ELIST,"ELIST"], expressionList);} - ; + : expression (COMMA! expression)* + {#expressionList = #(#[ELIST,"ELIST"], expressionList);} + ; // assignment expression (level 13) assignmentExpression - : conditionalExpression - ( ( ASSIGN^ + : conditionalExpression + ( ( ASSIGN^ | PLUS_ASSIGN^ | MINUS_ASSIGN^ | STAR_ASSIGN^ @@ -760,99 +760,99 @@ assignmentExpression | BXOR_ASSIGN^ | BOR_ASSIGN^ ) - assignmentExpression - )? - ; + assignmentExpression + )? + ; // conditional test (level 12) conditionalExpression - : logicalOrExpression - ( QUESTION^ assignmentExpression COLON! conditionalExpression )? - ; + : logicalOrExpression + ( QUESTION^ assignmentExpression COLON! conditionalExpression )? + ; // logical or (||) (level 11) logicalOrExpression - : logicalAndExpression (LOR^ logicalAndExpression)* - ; + : logicalAndExpression (LOR^ logicalAndExpression)* + ; // logical and (&&) (level 10) logicalAndExpression - : inclusiveOrExpression (LAND^ inclusiveOrExpression)* - ; + : inclusiveOrExpression (LAND^ inclusiveOrExpression)* + ; // bitwise or non-short-circuiting or (|) (level 9) inclusiveOrExpression - : exclusiveOrExpression (BOR^ exclusiveOrExpression)* - ; + : exclusiveOrExpression (BOR^ exclusiveOrExpression)* + ; // exclusive or (^) (level 8) exclusiveOrExpression - : andExpression (BXOR^ andExpression)* - ; + : andExpression (BXOR^ andExpression)* + ; // bitwise or non-short-circuiting and (&) (level 7) andExpression - : equalityExpression (BAND^ equalityExpression)* - ; + : equalityExpression (BAND^ equalityExpression)* + ; // equality/inequality (==/!=) (level 6) equalityExpression - : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)* - ; + : relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)* + ; // boolean relational expressions (level 5) relationalExpression - : shiftExpression - ( ( ( LT^ - | GT^ - | LE^ - | GE^ - ) - shiftExpression - )* - | "instanceof"^ typeSpec[true] - ) - ; + : shiftExpression + ( ( ( LT^ + | GT^ + | LE^ + | GE^ + ) + shiftExpression + )* + | "instanceof"^ typeSpec[true] + ) + ; // bit shift expressions (level 4) shiftExpression - : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)* - ; + : additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)* + ; // binary addition/subtraction (level 3) additiveExpression - : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)* - ; + : multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)* + ; // multiplication/division/modulo (level 2) multiplicativeExpression - : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)* - ; + : unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)* + ; unaryExpression - : INC^ unaryExpression - | DEC^ unaryExpression - | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression - | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression - | unaryExpressionNotPlusMinus - ; + : INC^ unaryExpression + | DEC^ unaryExpression + | MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression + | PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression + | unaryExpressionNotPlusMinus + ; unaryExpressionNotPlusMinus - : BNOT^ unaryExpression - | LNOT^ unaryExpression + : BNOT^ unaryExpression + | LNOT^ unaryExpression - // use predicate to skip cases like: (int.class) + // use predicate to skip cases like: (int.class) | (LPAREN builtInTypeSpec[true] RPAREN) => lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN! unaryExpression @@ -860,108 +860,108 @@ unaryExpressionNotPlusMinus // Have to backtrack to see if operator follows. If no operator // follows, it's a typecast. No semantic checking needed to parse. // if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)" - | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=> + | (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=> lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN! unaryExpressionNotPlusMinus - | postfixExpression - ; + | postfixExpression + ; // qualified names, array expressions, method invocation, post inc/dec postfixExpression - : + : /* "this"! lp1:LPAREN^ argList RPAREN! - {#lp1.setType(CTOR_CALL);} + {#lp1.setType(CTOR_CALL);} | "super"! lp2:LPAREN^ argList RPAREN! - {#lp2.setType(SUPER_CTOR_CALL);} + {#lp2.setType(SUPER_CTOR_CALL);} | */ primaryExpression - ( + ( /* options { - // the use of postfixExpression in SUPER_CTOR_CALL adds DOT - // to the lookahead set, and gives loads of false non-det - // warnings. - // shut them off. - generateAmbigWarnings=false; - } - : */ + // the use of postfixExpression in SUPER_CTOR_CALL adds DOT + // to the lookahead set, and gives loads of false non-det + // warnings. + // shut them off. + generateAmbigWarnings=false; + } + : */ DOT^ IDENT - ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} - argList - RPAREN! - )? - | DOT^ "this" + ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} + argList + RPAREN! + )? + | DOT^ "this" - | DOT^ "super" + | DOT^ "super" ( // (new Outer()).super() (create enclosing instance) lp3:LPAREN^ argList RPAREN! {#lp3.setType(SUPER_CTOR_CALL);} - | DOT^ IDENT - ( lps:LPAREN^ {#lps.setType(METHOD_CALL);} + | DOT^ IDENT + ( lps:LPAREN^ {#lps.setType(METHOD_CALL);} argList RPAREN! )? ) - | DOT^ newExpression - | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK! - )* + | DOT^ newExpression + | lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK! + )* - ( // possibly add on a post-increment or post-decrement. + ( // possibly add on a post-increment or post-decrement. // allows INC/DEC on too much, but semantics can check - in:INC^ {#in.setType(POST_INC);} - | de:DEC^ {#de.setType(POST_DEC);} - )? - ; + in:INC^ {#in.setType(POST_INC);} + | de:DEC^ {#de.setType(POST_DEC);} + )? + ; // the basic element of an expression primaryExpression - : identPrimary ( options {greedy=true;} : DOT^ "class" )? + : identPrimary ( options {greedy=true;} : DOT^ "class" )? | constant - | "true" - | "false" - | "null" + | "true" + | "false" + | "null" | newExpression - | "this" - | "super" - | LPAREN! assignmentExpression RPAREN! - // look for int.class and int[].class - | builtInType - ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* - DOT^ "class" - ; + | "this" + | "super" + | LPAREN! assignmentExpression RPAREN! + // look for int.class and int[].class + | builtInType + ( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )* + DOT^ "class" + ; /** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class, * and a.b.c.class refs. Also this(...) and super(...). Match * this or super. */ identPrimary - : IDENT - ( + : IDENT + ( options { - // .ident could match here or in postfixExpression. - // We do want to match here. Turn off warning. - greedy=true; - } - : DOT^ IDENT - )* - ( + // .ident could match here or in postfixExpression. + // We do want to match here. Turn off warning. + greedy=true; + } + : DOT^ IDENT + )* + ( options { - // ARRAY_DECLARATOR here conflicts with INDEX_OP in - // postfixExpression on LBRACK RBRACK. - // We want to match [] here, so greedy. This overcomes + // ARRAY_DECLARATOR here conflicts with INDEX_OP in + // postfixExpression on LBRACK RBRACK. + // We want to match [] here, so greedy. This overcomes // limitation of linear approximate lookahead. - greedy=true; - } - : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! ) - | ( options {greedy=true;} : + greedy=true; + } + : ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! ) + | ( options {greedy=true;} : lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK! )+ - )? + )? ; /** object instantiation. @@ -1014,53 +1014,53 @@ identPrimary * */ newExpression - : "new"^ type - ( LPAREN! argList RPAREN! (classBlock)? - - //java 1.1 - // Note: This will allow bad constructs like - // new int[4][][3] {exp,exp}. - // There needs to be a semantic check here... - // to make sure: - // a) [ expr ] and [ ] are not mixed - // b) [ expr ] and an init are not used together - - | newArrayDeclarator (arrayInitializer)? - ) - ; + : "new"^ type + ( LPAREN! argList RPAREN! (classBlock)? + + //java 1.1 + // Note: This will allow bad constructs like + // new int[4][][3] {exp,exp}. + // There needs to be a semantic check here... + // to make sure: + // a) [ expr ] and [ ] are not mixed + // b) [ expr ] and an init are not used together + + | newArrayDeclarator (arrayInitializer)? + ) + ; argList - : ( expressionList - | /*nothing*/ - {#argList = #[ELIST,"ELIST"];} - ) - ; + : ( expressionList + | /*nothing*/ + {#argList = #[ELIST,"ELIST"];} + ) + ; newArrayDeclarator - : ( - // CONFLICT: - // newExpression is a primaryExpression which can be - // followed by an array index reference. This is ok, - // as the generated code will stay in this loop as - // long as it sees an LBRACK (proper behavior) - options { - warnWhenFollowAmbig = false; - } - : - lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} - (expression)? - RBRACK! - )+ - ; + : ( + // CONFLICT: + // newExpression is a primaryExpression which can be + // followed by an array index reference. This is ok, + // as the generated code will stay in this loop as + // long as it sees an LBRACK (proper behavior) + options { + warnWhenFollowAmbig = false; + } + : + lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} + (expression)? + RBRACK! + )+ + ; constant - : NUM_INT - | CHAR_LITERAL - | STRING_LITERAL - | NUM_FLOAT - | NUM_LONG - | NUM_DOUBLE - ; + : NUM_INT + | CHAR_LITERAL + | STRING_LITERAL + | NUM_FLOAT + | NUM_LONG + | NUM_DOUBLE + ; //---------------------------------------------------------------------------- // The Java scanner @@ -1068,121 +1068,121 @@ constant class JavaLexer extends Lexer; options { - exportVocab=Java; // call the vocabulary "Java" - testLiterals=false; // don't automatically test for literals - k=4; // four characters of lookahead - charVocabulary='\u0003'..'\u7FFE'; - // without inlining some bitset tests, couldn't do unicode; - // I need to make ANTLR generate smaller bitsets; see - // bottom of JavaLexer.java - codeGenBitsetTestThreshold=20; + exportVocab=Java; // call the vocabulary "Java" + testLiterals=false; // don't automatically test for literals + k=4; // four characters of lookahead + charVocabulary='\u0003'..'\u7FFE'; + // without inlining some bitset tests, couldn't do unicode; + // I need to make ANTLR generate smaller bitsets; see + // bottom of JavaLexer.java + codeGenBitsetTestThreshold=20; } // OPERATORS -QUESTION : '?' ; -LPAREN : '(' ; -RPAREN : ')' ; -LBRACK : '[' ; -RBRACK : ']' ; -LCURLY : '{' ; -RCURLY : '}' ; -COLON : ':' ; -COMMA : ',' ; -//DOT : '.' ; -ASSIGN : '=' ; -EQUAL : "==" ; -LNOT : '!' ; -BNOT : '~' ; -NOT_EQUAL : "!=" ; -DIV : '/' ; -DIV_ASSIGN : "/=" ; -PLUS : '+' ; -PLUS_ASSIGN : "+=" ; -INC : "++" ; -MINUS : '-' ; -MINUS_ASSIGN : "-=" ; -DEC : "--" ; -STAR : '*' ; -STAR_ASSIGN : "*=" ; -MOD : '%' ; -MOD_ASSIGN : "%=" ; -SR : ">>" ; -SR_ASSIGN : ">>=" ; -BSR : ">>>" ; -BSR_ASSIGN : ">>>=" ; -GE : ">=" ; -GT : ">" ; -SL : "<<" ; -SL_ASSIGN : "<<=" ; -LE : "<=" ; -LT : '<' ; -BXOR : '^' ; -BXOR_ASSIGN : "^=" ; -BOR : '|' ; -BOR_ASSIGN : "|=" ; -LOR : "||" ; -BAND : '&' ; -BAND_ASSIGN : "&=" ; -LAND : "&&" ; -SEMI : ';' ; +QUESTION : '?' ; +LPAREN : '(' ; +RPAREN : ')' ; +LBRACK : '[' ; +RBRACK : ']' ; +LCURLY : '{' ; +RCURLY : '}' ; +COLON : ':' ; +COMMA : ',' ; +//DOT : '.' ; +ASSIGN : '=' ; +EQUAL : "==" ; +LNOT : '!' ; +BNOT : '~' ; +NOT_EQUAL : "!=" ; +DIV : '/' ; +DIV_ASSIGN : "/=" ; +PLUS : '+' ; +PLUS_ASSIGN : "+=" ; +INC : "++" ; +MINUS : '-' ; +MINUS_ASSIGN : "-=" ; +DEC : "--" ; +STAR : '*' ; +STAR_ASSIGN : "*=" ; +MOD : '%' ; +MOD_ASSIGN : "%=" ; +SR : ">>" ; +SR_ASSIGN : ">>=" ; +BSR : ">>>" ; +BSR_ASSIGN : ">>>=" ; +GE : ">=" ; +GT : ">" ; +SL : "<<" ; +SL_ASSIGN : "<<=" ; +LE : "<=" ; +LT : '<' ; +BXOR : '^' ; +BXOR_ASSIGN : "^=" ; +BOR : '|' ; +BOR_ASSIGN : "|=" ; +LOR : "||" ; +BAND : '&' ; +BAND_ASSIGN : "&=" ; +LAND : "&&" ; +SEMI : ';' ; // Whitespace -- ignored -WS : ( ' ' - | '\t' - | '\f' - // handle newlines - | ( options {generateAmbigWarnings=false;} - : "\r\n" // Evil DOS - | '\r' // Macintosh - | '\n' // Unix (the right way) - ) - { newline(); } - )+ - { _ttype = Token.SKIP; } - ; +WS : ( ' ' + | '\t' + | '\f' + // handle newlines + | ( options {generateAmbigWarnings=false;} + : "\r\n" // Evil DOS + | '\r' // Macintosh + | '\n' // Unix (the right way) + ) + { newline(); } + )+ + { _ttype = Token.SKIP; } + ; // Single-line comments SL_COMMENT - : "//" - (~('\n'|'\r'))* ('\n'|'\r'('\n')?)? - {$setType(Token.SKIP); newline();} - ; + : "//" + (~('\n'|'\r'))* ('\n'|'\r'('\n')?)? + {$setType(Token.SKIP); newline();} + ; // multiple-line comments ML_COMMENT - : "/*" - ( /* '\r' '\n' can be matched in one alternative or by matching - '\r' in one iteration and '\n' in another. I am trying to - handle any flavor of newline that comes in, but the language - that allows both "\r\n" and "\r" and "\n" to all be valid - newline is ambiguous. Consequently, the resulting grammar - must be ambiguous. I'm shutting this warning off. - */ - options { - generateAmbigWarnings=false; - } - : - { LA(2)!='/' }? '*' - | '\r' '\n' {newline();} - | '\r' {newline();} - | '\n' {newline();} - | ~('*'|'\n'|'\r') - )* - "*/" - {$setType(Token.SKIP);} - ; + : "/*" + ( /* '\r' '\n' can be matched in one alternative or by matching + '\r' in one iteration and '\n' in another. I am trying to + handle any flavor of newline that comes in, but the language + that allows both "\r\n" and "\r" and "\n" to all be valid + newline is ambiguous. Consequently, the resulting grammar + must be ambiguous. I'm shutting this warning off. + */ + options { + generateAmbigWarnings=false; + } + : + { LA(2)!='/' }? '*' + | '\r' '\n' {newline();} + | '\r' {newline();} + | '\n' {newline();} + | ~('*'|'\n'|'\r') + )* + "*/" + {$setType(Token.SKIP);} + ; // character literals CHAR_LITERAL - : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\'' - ; + : '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\'' + ; // string literals STRING_LITERAL - : '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"' - ; + : '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"' + ; // escape sequence -- note that this is protected; it can only be called @@ -1195,121 +1195,132 @@ STRING_LITERAL // the FOLLOW ambig warnings. protected ESC - : '\\' - ( 'n' - | 'r' - | 't' - | 'b' - | 'f' - | '"' - | '\'' - | '\\' - | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT - | '0'..'3' - ( - options { - warnWhenFollowAmbig = false; - } - : '0'..'7' - ( - options { - warnWhenFollowAmbig = false; - } - : '0'..'7' - )? - )? - | '4'..'7' - ( - options { - warnWhenFollowAmbig = false; - } - : '0'..'7' - )? - ) - ; + : '\\' + ( 'n' + | 'r' + | 't' + | 'b' + | 'f' + | '"' + | '\'' + | '\\' + | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT + | '0'..'3' + ( + options { + warnWhenFollowAmbig = false; + } + : '0'..'7' + ( + options { + warnWhenFollowAmbig = false; + } + : '0'..'7' + )? + )? + | '4'..'7' + ( + options { + warnWhenFollowAmbig = false; + } + : '0'..'7' + )? + ) + ; // hexadecimal digit (again, note it's protected!) protected HEX_DIGIT - : ('0'..'9'|'A'..'F'|'a'..'f') - ; + : ('0'..'9'|'A'..'F'|'a'..'f') + ; // an identifier. Note that testLiterals is set to true! This means // that after we match the rule, we look in the literals table to see // if it's a literal or really an identifer IDENT - options {testLiterals=true;} - : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')* - ; + options {testLiterals=true;} + : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')* + ; // a numeric literal NUM_INT - {boolean isDecimal=false; Token t=null;} + {boolean isDecimal=false, isHexadecimal=false; Token t=null;} : '.' {_ttype = DOT;} - ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})? + ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})? { - if (t != null && t.getText().toUpperCase().indexOf('F')>=0) { - _ttype = NUM_FLOAT; - } - else { - _ttype = NUM_DOUBLE; // assume double - } - } + if (t != null && t.getText().toUpperCase().indexOf('F')>=0) { + _ttype = NUM_FLOAT; + } + else { + _ttype = NUM_DOUBLE; // assume double + } + } )? - | ( '0' {isDecimal = true;} // special case for just '0' - ( ('x'|'X') - ( // hex - // the 'e'|'E' and float suffix stuff look - // like hex digits, hence the (...)+ doesn't - // know when to stop: ambig. ANTLR resolves - // it correctly by matching immediately. It - // is therefor ok to hush warning. - options { - warnWhenFollowAmbig=false; - } - : HEX_DIGIT - )+ - - | //float or double with leading zero - (('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+ - - | ('0'..'7')+ // octal - )? - | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal - ) - ( ('l'|'L') { _ttype = NUM_LONG; } - - // only check to see if it's a float if looks like decimal so far - | {isDecimal}? - ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})? - | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})? - | f4:FLOAT_SUFFIX {t=f4;} - ) - { - if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) { - _ttype = NUM_FLOAT; - } - else { - _ttype = NUM_DOUBLE; // assume double - } - } + | ( '0' {isDecimal = true;} // special case for just '0' + ( ('x'|'X') { isHexadecimal=true; } // hex + ( + // the 'e'|'E' and float suffix stuff look + // like hex digits, hence the (...)+ doesn't + // know when to stop: ambig. ANTLR resolves + // it correctly by matching immediately. It + // is therefor ok to hush warning. + options { + warnWhenFollowAmbig=false; + } + : HEX_DIGIT + )+ + + | //float or double with leading zero + (('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+ + + | ('0'..'7')+ // octal + )? + | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal + ) + ( + ('l'|'L') { _ttype = NUM_LONG; } + + // check to see if it's a hexadecimal w/ binary exponent float if looks like hexadecimal so far + | {isHexadecimal}? + ( '.' ( options { warnWhenFollowAmbig=false; } : HEX_DIGIT )* )? + ('p'|'P') ('+'|'-')? ('0'..'9')+ (f5:FLOAT_SUFFIX {t=f5;})? + { + if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) { + _ttype = NUM_FLOAT; + } else { + _ttype = NUM_DOUBLE; // assume double + } + } + // check to see if it's a float if looks like decimal so far + | {isDecimal}? + ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})? + | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})? + | f4:FLOAT_SUFFIX {t=f4;} + ) + { + if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) { + _ttype = NUM_FLOAT; + } else { + _ttype = NUM_DOUBLE; // assume double + } + } )? - ; + ; // a couple protected methods to assist in matching floating point numbers protected EXPONENT - : ('e'|'E') ('+'|'-')? ('0'..'9')+ - ; + : ('e'|'E') (PLUS|MINUS)? ('0'..'9')+ + ; protected FLOAT_SUFFIX - : 'f'|'F'|'d'|'D' - ; + : 'f'|'F'|'d'|'D' + ; diff --git a/src/java/com/jogamp/gluegen/ConstantDefinition.java b/src/java/com/jogamp/gluegen/ConstantDefinition.java index e88bb9c..f8f4973 100644 --- a/src/java/com/jogamp/gluegen/ConstantDefinition.java +++ b/src/java/com/jogamp/gluegen/ConstantDefinition.java @@ -33,6 +33,8 @@ package com.jogamp.gluegen; +import java.util.regex.Pattern; + import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider; import com.jogamp.gluegen.cgram.types.AliasedSymbol.AliasedSymbolImpl; import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol; @@ -198,38 +200,6 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema } return false; } - public static boolean isNumber(final String s) { - if( isHexNumber(s) ) { - return true; - } else { - return isDecimalNumber(s); - } - } - public static boolean isHexNumber(final String s) { - return patternHexNumber.matcher(s).matches(); - } - public static java.util.regex.Pattern patternHexNumber = - java.util.regex.Pattern.compile("0[xX][0-9a-fA-F]+[lLfFuU]?"); - - public static boolean isDecimalNumber(final String s) { - try { - Float.valueOf(s); - } catch (final NumberFormatException e) { - // not parsable as a number - return false; - } - return true; - } - - - public static boolean isCPPOperand(final String s) { - return patternCPPOperand.matcher(s).matches(); - } - /** - * One of: {@code +} {@code -} {@code *} {@code /} {@code |} {@code &} {@code (} {@code )} {@code <<} {@code >>} - */ - public static java.util.regex.Pattern patternCPPOperand = - java.util.regex.Pattern.compile("[\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)"); public static boolean isIdentifier(final String value) { boolean identifier = false; @@ -251,4 +221,91 @@ public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSema } return identifier; } + + public static boolean isNumber(final String s) { + if( isHexNumber(s) ) { + return true; + } else { + return isDecimalNumber(s); + } + } + public static boolean isHexNumber(final String s) { + return patternHexNumber.matcher(s).matches(); + } + public static Pattern patternHexNumber = Pattern.compile("0[xX][0-9a-fA-F]+[lLfFuU]?"); + + /** + * Complete pattern for floating point number, + * compatible and described in {@link Double#valueOf(String)}. + */ + public static Pattern patternDecimalNumber; + private static String fpRegex; + static { + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?" + // Optional sign character + "("+ + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + "("+ + "("+ + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal w/ binary exponent + "(" + + "(" + + // Hexadecimal strings + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + ")" + + + // binary exponent + "[pP][+-]?" + Digits + + ")" + + ")" + + "[fFdD]?"+ + ")"+ + ")" + + "[\\x00-\\x20]*"// Optional trailing "whitespace" + ); + patternDecimalNumber = Pattern.compile(fpRegex); + } + public static boolean isDecimalNumber(final String s) { + return patternDecimalNumber.matcher(s).matches(); + } + + public static boolean isCPPOperand(final String s) { + return patternCPPOperand.matcher(s).matches(); + } + /** + * One of: {@code +} {@code -} {@code *} {@code /} {@code |} {@code &} {@code (} {@code )} {@code <<} {@code >>} + *

+ * Expression excludes {@link #patternDecimalNumber}. + *

+ */ + public static Pattern patternCPPOperand = Pattern.compile("(?!"+fpRegex+")[\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)"); + } diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index ae4ed2a..5fb281f 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -384,7 +384,7 @@ public class JavaEmitter implements GlueEmitter { final double dVal = Double.parseDouble(value); final double absVal = Math.abs(dVal); // if constant is small enough, store it as a float instead of a double - if (absVal < Float.MIN_VALUE || absVal > Float.MAX_VALUE) { + if (absVal < Float.MIN_VALUE || absVal > Float.MAX_VALUE || lastChar == 'd' || lastChar == 'D' ) { return new Double(dVal); } return new Float((float) dVal); @@ -448,10 +448,11 @@ public class JavaEmitter implements GlueEmitter { javaWriter().println(" /** " + optionalComment + " */"); } String suffix = ""; - if(!value.endsWith(")")) { - if (type.equals("float") && !value.endsWith("f")) { + final char lastChar = value.charAt(value.length()-1); + if( lastChar != ')' ) { + if (type.equals("float") && lastChar != 'f' && lastChar != 'F' ) { suffix = "f"; - }else if(value.endsWith("u") || value.endsWith("U")) { + }else if( lastChar == 'u' || lastChar == 'U' ) { value = value.substring(0, value.length()-1); } } diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java index 32ec496..b5f4f2c 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java @@ -73,6 +73,8 @@ public class BaseClass extends SingletonJunitCase { (obj instanceof com.jogamp.gluegen.test.junit.generation.Bindingtest1)); } + public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d + /** * Verifies if all generated method signatures are completed, * ie a compilation only coverage test without functional tests. @@ -122,6 +124,36 @@ public class BaseClass extends SingletonJunitCase { Assert.assertEquals( 8, Bindingtest1.NUMBER_EIGHT); Assert.assertEquals( 9, Bindingtest1.NUMBER_NINE); Assert.assertEquals( 10, Bindingtest1.NUMBER_TEN); + + + // Floating point hexadecimals + final float CL_FLT_A0 = Bindingtest1.CL_FLT_A0; + final float CL_FLT_A1 = Bindingtest1.CL_FLT_A1; + final float CL_FLT_A2 = Bindingtest1.CL_FLT_A2; + Assert.assertEquals( 0x1.p127f, CL_FLT_A0, EPSILON); + Assert.assertEquals( 0x1.p+127F, CL_FLT_A1, EPSILON); + Assert.assertEquals( 0x1.p-127f, CL_FLT_A2, EPSILON); + + final float CL_FLT_EPSILON = Bindingtest1.CL_FLT_EPSILON; + final double CL_FLT_MAX= Bindingtest1.CL_FLT_MAX; + final double CL_FLT_MIN = Bindingtest1.CL_FLT_MIN; + Assert.assertEquals( 0x1.0p-23f, CL_FLT_EPSILON, EPSILON); + Assert.assertEquals( 0x1.fffffep127f, CL_FLT_MAX, EPSILON); + Assert.assertEquals( 0x1.0p-126f, CL_FLT_MIN, EPSILON); + + final double CL_DBL_B0 = Bindingtest1.CL_DBL_B0; + final double CL_DBL_B1 = Bindingtest1.CL_DBL_B1; + final double CL_DBL_B2 = Bindingtest1.CL_DBL_B2; + Assert.assertEquals( 0x1.p127d, CL_DBL_B0, EPSILON); + Assert.assertEquals( 0x1.p+127D, CL_DBL_B1, EPSILON); + Assert.assertEquals( 0x1.p-127d, CL_DBL_B2, EPSILON); + + final float CL_DBL_EPSILON = Bindingtest1.CL_DBL_EPSILON; + final double CL_DBL_MAX= Bindingtest1.CL_DBL_MAX; + final double CL_DBL_MIN = Bindingtest1.CL_DBL_MIN; + Assert.assertEquals( 0x1.0p-52f, CL_DBL_EPSILON, EPSILON); + Assert.assertEquals( 0x1.fffffffffffffp1023, CL_DBL_MAX, EPSILON); + Assert.assertEquals( 0x1.0p-1022, CL_DBL_MIN, EPSILON); } { l = binding.testXID(l); @@ -1233,8 +1265,6 @@ public class BaseClass extends SingletonJunitCase { } } - public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d - /** Test array and pointer bindings of structs */ public void chapter12TestStructArrayModelConst(final Bindingtest1 binding) throws Exception { final TK_ModelConst model = binding.createModelConst(); diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h index fa876c6..4e60114 100644 --- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h +++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h @@ -39,6 +39,22 @@ typedef void * AnonBuffer; // Non Opaque // typedef XID XID_2; // Duplicate w/ compatible type (ignored) - OpenSolaris: Native gcc error // typedef int XID_2; // Duplicate w/ incompatible type ERROR +#define CL_FLT_A0 0x1p127 +#define CL_FLT_A1 0x1p+127F +#define CL_FLT_A2 0x1p-127f + +#define CL_DBL_B0 0x1.p127d +#define CL_DBL_B1 0x1.p+127D +#define CL_DBL_B2 0x1.p-127d + +#define CL_FLT_MAX 0x1.fffffep127f +#define CL_FLT_MIN 0x1.0p-126f +#define CL_FLT_EPSILON 0x1.0p-23f + +#define CL_DBL_MAX 0x1.fffffffffffffp1023 +#define CL_DBL_MIN 0x1.0p-1022 +#define CL_DBL_EPSILON 0x1.0p-52 + #define DEFINE_01 1234 #define DEFINE_01 1234 // Duplicate w/ same value (ignored) // #define DEFINE_01 1235 // Duplicate w/ diff value ERROR -- cgit v1.2.3