001/*-------------------------------------------------------------------------+ 002| | 003| Copyright (c) 2009-2018 CQSE GmbH | 004| | 005+-------------------------------------------------------------------------*/ 006package eu.cqse.check.cpp; 007 008import java.util.regex.Pattern; 009 010/** 011 * Parser for C++ integer literals, see 012 * https://en.cppreference.com/w/cpp/language/integer_literal 013 */ 014public class CppIntegerLiteralParser { 015 016 private static String DECIMAL_LITERAL_PATTERN = "[0-9']+"; 017 018 private static String HEX_LITERAL_PATTERN = "0x[0-9a-f']+"; 019 020 private static String OCTAL_LITERAL_PATTERN = "0[0-8']+"; 021 022 private static String BINARY_LITERAL_PATTERN = "0b[01']+"; 023 024 /** Suffix to indicate the type of the integer literal. */ 025 private static String INTEGER_SUFFIX_PATTERN = "(u|l|ll|ul|ull|lu|llu)?"; 026 027 /** 028 * String literals matching this pattern are valid integer literals. 029 */ 030 private static Pattern INTEGER_LITERAL_PATTERN = Pattern 031 .compile("(" + DECIMAL_LITERAL_PATTERN + "|" + HEX_LITERAL_PATTERN + "|" + OCTAL_LITERAL_PATTERN + "|" 032 + BINARY_LITERAL_PATTERN + ")" + INTEGER_SUFFIX_PATTERN, Pattern.CASE_INSENSITIVE); 033 034 /** Checks if the given string literal is a valid C++ integer literal. */ 035 public static boolean isInteger(String literal) { 036 return INTEGER_LITERAL_PATTERN.matcher(literal).matches(); 037 } 038 039 /** Parses the string literal, if it is valid. */ 040 public static int parse(String literal) { 041 if (!isInteger(literal)) { 042 throw new NumberFormatException(literal + " is not a valid C++ integer literal"); 043 } 044 int base = 10; 045 if (literal.startsWith("0x") || literal.startsWith("0X")) { 046 base = 16; 047 literal = literal.substring(2); 048 } else if (literal.startsWith("0b") || literal.startsWith("0B")) { 049 base = 2; 050 literal = literal.substring(2); 051 } else if (literal.startsWith("0")) { 052 base = 8; 053 } 054 literal = removeInvalidCharacters(literal); 055 return Integer.parseInt(literal, base); 056 } 057 058 private static String removeInvalidCharacters(String literal) { 059 literal = literal.replace("\'", ""); 060 literal = literal.replace("u", ""); 061 literal = literal.replace("l", ""); 062 literal = literal.replace("U", ""); 063 literal = literal.replace("L", ""); 064 return literal; 065 } 066 067}