/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package de.monticore.literals;
import java.io.CharConversionException;
/**
* This class provides methods for converting literals. The LiteralsHelper is a singleton.
*
* @author Martin Schindler
*/
public class LiteralsHelper {
private static LiteralsHelper instance;
/**
* We have a singleton.
*/
private LiteralsHelper() {
}
/**
* Returns the singleton instance.
*
* @return The instance.
*/
public static LiteralsHelper getInstance() {
if (instance == null) {
instance = new LiteralsHelper();
}
return instance;
}
/**
* Decodes a char literal into a char
*
* @param s char literal as string including "'"
* @return decoded char
* @throws CharConversionException
*/
public char decodeChar(String s) throws CharConversionException {
if (s.length() == 1) { // single char
return s.charAt(0);
}
else if (s.length() == 2 && s.charAt(0) == '\\') { // escape sequence
switch (s.charAt(1)) {
case 'b':
return '\b';
case 't':
return '\t';
case 'n':
return '\n';
case 'f':
return '\f';
case 'r':
return '\r';
case '"':
return '\"';
case '\'':
return '\'';
case '\\':
return '\\';
default:
break;
}
}
else if (s.charAt(0) == '\\' && s.charAt(1) == 'u') { // unicode
return (char) Integer.parseInt(s.substring(2), 16);
}
throw new CharConversionException("0xA4080 Unable to convert String " + s + " to char.");
}
/**
* Decodes a string literal into a string
*
* @param s string literal excluding '"'
* @return decoded string
* @throws CharConversionException
*/
public String decodeString(String s) throws CharConversionException {
StringBuilder ret = new StringBuilder();
String in = s;
while (in.length() != 0) {
if (in.charAt(0) == '\\') {
if (in.charAt(1) == 'u') { // unicode
ret.append(decodeChar(in.substring(0, 6)));
in = in.substring(6);
}
else { // escape sequence
ret.append(decodeChar(in.substring(0, 2)));
in = in.substring(2);
}
}
else { // single char
ret.append(in.charAt(0));
in = in.substring(1);
}
}
return ret.toString();
}
/**
* Decodes an int literal into an int
*
* @param s int literal as string including '"'
* @return decoded int
*/
public int decodeInt(String s) {
int radix = 10;
if (s.startsWith("0") && s.length() > 1) {
if (s.startsWith("0x") || s.startsWith("0X")) {
return Integer.parseInt(s.substring(2), 16);
}
else {
radix = 8;
}
}
return Integer.parseInt(s, radix);
}
/**
* Decodes a long literal into a long
*
* @param s long literal as string including '"'
* @return decoded long
*/
public long decodeLong(String s) {
int radix = 10;
String in = s;
if (s.startsWith("0") && s.length() > 2) {
if (s.startsWith("0x") || s.startsWith("0X")) {
radix = 16;
in = s.substring(2);
}
else {
radix = 8;
}
}
return Long.parseLong(in.substring(0, in.length() - 1), radix);
}
/**
* Decodes a float literal into a float
*
* @param s float literal as string including '"'
* @return decoded float
*/
public float decodeFloat(String s) {
// workaround as parseFloat() does not parse 0xp1F correctly
if (s.toLowerCase().startsWith("0xp")) {
return Float.parseFloat("0x0p" + s.substring(3)); // 0xp1F == 0x0p1F == 0.0
}
return Float.parseFloat(s);
}
/**
* Decodes a double literal into a double
*
* @param s double literal as string including '"'
* @return decoded double
*/
public double decodeDouble(String s) {
// workaround as parseDouble() does not parse 0xp1 correctly
if (s.toLowerCase().startsWith("0xp")) {
return Double.parseDouble("0x0p" + s.substring(3)); // 0xp1 == 0x0p1 == 0.0
}
return Double.parseDouble(s);
}
}