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 --- .../com/jogamp/gluegen/ConstantDefinition.java | 121 +++++++++++++++------ src/java/com/jogamp/gluegen/JavaEmitter.java | 9 +- 2 files changed, 94 insertions(+), 36 deletions(-) (limited to 'src/java') 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); } } -- cgit v1.2.3