mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +02:00
Bug 519062: add support for digit separators
Change-Id: I6fa990c76395dcc6f9b0e5e05707cff03a34b8db Signed-off-by: Vlad Ivanov <vlad@ivanov.email>
This commit is contained in:
parent
b9bac6912e
commit
7d9e0b0ddd
10 changed files with 100 additions and 19 deletions
|
@ -12653,4 +12653,23 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
||||||
public void testNestedNamespaceDefinition_490359() throws Exception {
|
public void testNestedNamespaceDefinition_490359() throws Exception {
|
||||||
parseAndCheckBindings();
|
parseAndCheckBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constexpr auto l_a = 0b01'100'100'100;
|
||||||
|
// constexpr auto l_b = 1'123'456;
|
||||||
|
// constexpr auto l_c = 0x1000'1000;
|
||||||
|
// constexpr auto l_d = 0111'1000;
|
||||||
|
// auto v_a = 1'123'456ul;
|
||||||
|
// auto v_b = 1'123'456ull;
|
||||||
|
// auto v_c = 0xAABB'CCDDll;
|
||||||
|
public void testLiteralDecimalSeparators_519062() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
helper.assertVariableValue("l_a", 804);
|
||||||
|
helper.assertVariableValue("l_b", 1123456);
|
||||||
|
helper.assertVariableValue("l_c", 268439552);
|
||||||
|
helper.assertVariableValue("l_d", 299520);
|
||||||
|
|
||||||
|
helper.assertVariableType("v_a", CPPBasicType.UNSIGNED_LONG);
|
||||||
|
helper.assertVariableType("v_b", CPPBasicType.UNSIGNED_LONG_LONG);
|
||||||
|
helper.assertVariableType("v_c", CPPBasicType.LONG_LONG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class LexerTests extends BaseTestCase {
|
||||||
NO_MINMAX.fSupportMinAndMax= false;
|
NO_MINMAX.fSupportMinAndMax= false;
|
||||||
SLASH_PERCENT.fSupportSlashPercentComments= true;
|
SLASH_PERCENT.fSupportSlashPercentComments= true;
|
||||||
CPP_OPTIONS.fSupportRawStringLiterals= true;
|
CPP_OPTIONS.fSupportRawStringLiterals= true;
|
||||||
|
CPP_OPTIONS.fSupportDigitSeparators= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String TRIGRAPH_REPLACES_CHARS= "#^[]|{}~\\";
|
static String TRIGRAPH_REPLACES_CHARS= "#^[]|{}~\\";
|
||||||
|
@ -453,6 +454,14 @@ public class LexerTests extends BaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNumberSeparator() throws Exception {
|
||||||
|
String n = "123'456";
|
||||||
|
|
||||||
|
init(n, CPP_OPTIONS);
|
||||||
|
integer(n);
|
||||||
|
eof();
|
||||||
|
}
|
||||||
|
|
||||||
public void testCharLiteral() throws Exception {
|
public void testCharLiteral() throws Exception {
|
||||||
String lit= "'abc0123\\'\".:; \\\\'";
|
String lit= "'abc0123\\'\".:; \\\\'";
|
||||||
init(lit);
|
init(lit);
|
||||||
|
|
|
@ -121,6 +121,11 @@ public abstract class AbstractScannerExtensionConfiguration implements IScannerE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportDigitSeparators() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharArrayIntMap getAdditionalPreprocessorKeywords() {
|
public CharArrayIntMap getAdditionalPreprocessorKeywords() {
|
||||||
return fAddPreprocessorKeywords;
|
return fAddPreprocessorKeywords;
|
||||||
|
|
|
@ -98,6 +98,12 @@ public abstract class GNUScannerExtensionConfiguration extends AbstractScannerEx
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportDigitSeparators() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated simply derive from this class and use {@link #addMacro(String, String)} to
|
* @deprecated simply derive from this class and use {@link #addMacro(String, String)} to
|
||||||
* add additional macros.
|
* add additional macros.
|
||||||
|
|
|
@ -120,4 +120,10 @@ public interface IScannerExtensionConfiguration {
|
||||||
* @since 5.11
|
* @since 5.11
|
||||||
*/
|
*/
|
||||||
public boolean supportUserDefinedLiterals();
|
public boolean supportUserDefinedLiterals();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for C++14 digit separators in integer literals
|
||||||
|
* @since 6.5
|
||||||
|
*/
|
||||||
|
public boolean supportDigitSeparators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,4 +197,9 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
|
||||||
public boolean supportUserDefinedLiterals() {
|
public boolean supportUserDefinedLiterals() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportDigitSeparators() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -511,7 +511,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
* 0
|
* 0
|
||||||
* octal-literal octal-digit
|
* octal-literal octal-digit
|
||||||
*/
|
*/
|
||||||
while (isOctal(c) && i < value.length) {
|
while (isOctalOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -539,7 +539,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
* decimal-literal digit
|
* decimal-literal digit
|
||||||
*/
|
*/
|
||||||
c = value[i];
|
c = value[i];
|
||||||
while (Character.isDigit(c) && i < value.length) {
|
while (isDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
*/
|
*/
|
||||||
private static int afterDecimalPoint(char[] value, int i) {
|
private static int afterDecimalPoint(char[] value, int i) {
|
||||||
char c = value[++i];
|
char c = value[++i];
|
||||||
while (Character.isDigit(c) && i < value.length) {
|
while (isDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,7 +592,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Character.isDigit(c) && i < value.length) {
|
while (isDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
// If there were no digits following the 'e' then we have
|
// If there were no digits following the 'e' then we have
|
||||||
|
@ -606,7 +606,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
char c = value[++i];
|
char c = value[++i];
|
||||||
|
|
||||||
if (c == '1' || c == '0') {
|
if (c == '1' || c == '0') {
|
||||||
while (c == '1' || c == '0' && i < value.length) {
|
while (c == '1' || c == '0' || c == '\'' && i < value.length) {
|
||||||
c = value[i++];
|
c = value[i++];
|
||||||
}
|
}
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
|
@ -615,7 +615,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
} else if (c == '.') {
|
} else if (c == '.') {
|
||||||
// no such thing as binary floating point
|
// no such thing as binary floating point
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
while (Character.isDigit(c) && i < value.length) {
|
while (isDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[i++];
|
c = value[i++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,8 +633,8 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
* hexadecimal-literal hexadecimal-digit
|
* hexadecimal-literal hexadecimal-digit
|
||||||
*/
|
*/
|
||||||
char c = value[++i];
|
char c = value[++i];
|
||||||
if (isHexDigit(c)) {
|
if (isHexDigitOrSeparator(c)) {
|
||||||
while (isHexDigit(c) && i < value.length) {
|
while (isHexDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
|
@ -654,8 +654,8 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
private static int hexFloatAfterDecimal(char[] value, int i) {
|
private static int hexFloatAfterDecimal(char[] value, int i) {
|
||||||
// 0xHHH.
|
// 0xHHH.
|
||||||
char c = value[++i];
|
char c = value[++i];
|
||||||
if (isHexDigit(c)) {
|
if (isHexDigitOrSeparator(c)) {
|
||||||
while (isHexDigit(c) && i < value.length) {
|
while (isHexDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +683,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
while (Character.isDigit(c) && i < value.length) {
|
while (isDigitOrSeparator(c) && i < value.length) {
|
||||||
c = value[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -692,13 +692,17 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isHexDigit(char c) {
|
private static boolean isHexDigitOrSeparator(char c) {
|
||||||
c |= 0x20;
|
char lc = Character.toLowerCase(c);
|
||||||
return ((c <= 'f' && c >= 'a') || (c <= '9' && c >= '0'));
|
return (lc <= 'f' && lc >= 'a') || (c <= '9' && c >= '0') || (c == '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isOctal(final char c) {
|
private static boolean isOctalOrSeparator(final char c) {
|
||||||
return c >= '0' && c <= '7';
|
return (c >= '0' && c <= '7') || (c == '\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDigitOrSeparator(final char c) {
|
||||||
|
return Character.isDigit(c) || (c == '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -323,6 +323,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals();
|
fLexOptions.fSupportUTFLiterals = configuration.supportUTFLiterals();
|
||||||
fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals();
|
fLexOptions.fSupportRawStringLiterals = configuration.supportRawStringLiterals();
|
||||||
fLexOptions.fSupportUserDefinedLiterals = configuration.supportUserDefinedLiterals();
|
fLexOptions.fSupportUserDefinedLiterals = configuration.supportUserDefinedLiterals();
|
||||||
|
fLexOptions.fSupportDigitSeparators = configuration.supportDigitSeparators();
|
||||||
if (info instanceof ExtendedScannerInfo)
|
if (info instanceof ExtendedScannerInfo)
|
||||||
fLexOptions.fIncludeExportPatterns = ((ExtendedScannerInfo) info).getIncludeExportPatterns();
|
fLexOptions.fIncludeExportPatterns = ((ExtendedScannerInfo) info).getIncludeExportPatterns();
|
||||||
fLocationMap= new LocationMap(fLexOptions);
|
fLocationMap= new LocationMap(fLexOptions);
|
||||||
|
@ -1070,6 +1071,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
switch (image[pos]) {
|
switch (image[pos]) {
|
||||||
case '0': case'1':
|
case '0': case'1':
|
||||||
continue;
|
continue;
|
||||||
|
case '\'':
|
||||||
|
if (fLexOptions.fSupportDigitSeparators) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
case 'e': case 'E':
|
case 'e': case 'E':
|
||||||
case '.':
|
case '.':
|
||||||
handleProblem(IProblem.SCANNER_FLOAT_WITH_BAD_PREFIX, "0b".toCharArray(), number.getOffset(), number.getEndOffset()); //$NON-NLS-1$
|
handleProblem(IProblem.SCANNER_FLOAT_WITH_BAD_PREFIX, "0b".toCharArray(), number.getOffset(), number.getEndOffset()); //$NON-NLS-1$
|
||||||
|
@ -1108,6 +1115,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
hasDot= true;
|
hasDot= true;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// C++14 literal separator
|
||||||
|
case '\'':
|
||||||
|
if (fLexOptions.fSupportDigitSeparators) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
|
||||||
// check for exponent or hex digit
|
// check for exponent or hex digit
|
||||||
case 'E': case 'e':
|
case 'E': case 'e':
|
||||||
if (isHex && !hasExponent) {
|
if (isHex && !hasExponent) {
|
||||||
|
|
|
@ -439,6 +439,10 @@ public class ExpressionEvaluator {
|
||||||
int i = from;
|
int i = from;
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
for (; i < to; i++) {
|
for (; i < to; i++) {
|
||||||
|
if (tokenImage[i] == '\'') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int digit = getDigit(tokenImage[i]);
|
int digit = getDigit(tokenImage[i]);
|
||||||
if (digit >= base) {
|
if (digit >= base) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -59,6 +59,7 @@ final public class Lexer implements ITokenSequence {
|
||||||
public boolean fSupportUTFLiterals= true;
|
public boolean fSupportUTFLiterals= true;
|
||||||
public boolean fSupportRawStringLiterals= false;
|
public boolean fSupportRawStringLiterals= false;
|
||||||
public boolean fSupportUserDefinedLiterals = false;
|
public boolean fSupportUserDefinedLiterals = false;
|
||||||
|
public boolean fSupportDigitSeparators = false;
|
||||||
public IncludeExportPatterns fIncludeExportPatterns;
|
public IncludeExportPatterns fIncludeExportPatterns;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1034,6 +1035,13 @@ final public class Lexer implements ITokenSequence {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// C++ 14 literal separator
|
||||||
|
case '\'':
|
||||||
|
if (!fOptions.fSupportDigitSeparators) {
|
||||||
|
isPartOfNumber = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case END_OF_INPUT:
|
case END_OF_INPUT:
|
||||||
if (fSupportContentAssist) {
|
if (fSupportContentAssist) {
|
||||||
throw new OffsetLimitReachedException(ORIGIN_LEXER,
|
throw new OffsetLimitReachedException(ORIGIN_LEXER,
|
||||||
|
|
Loading…
Add table
Reference in a new issue