LiteralInterpreter.java

package edu.udel.cis.vsl.abc.ast.node.common;

import java.math.BigInteger;

import edu.udel.cis.vsl.abc.ast.node.IF.expression.FloatingConstantNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.IntegerConstantNode;
import edu.udel.cis.vsl.abc.ast.node.common.expression.CommonFloatingConstantNode;
import edu.udel.cis.vsl.abc.ast.node.common.expression.CommonIntegerConstantNode;
import edu.udel.cis.vsl.abc.ast.type.IF.FloatingType;
import edu.udel.cis.vsl.abc.ast.type.IF.IntegerType;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardBasicType.BasicTypeKind;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardSignedIntegerType;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardSignedIntegerType.SignedIntKind;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardUnsignedIntegerType;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardUnsignedIntegerType.UnsignedIntKind;
import edu.udel.cis.vsl.abc.ast.type.IF.TypeFactory;
import edu.udel.cis.vsl.abc.ast.value.IF.IntegerValue;
import edu.udel.cis.vsl.abc.ast.value.IF.RealFloatingValue;
import edu.udel.cis.vsl.abc.ast.value.IF.ValueFactory;
import edu.udel.cis.vsl.abc.token.IF.Source;
import edu.udel.cis.vsl.abc.token.IF.SyntaxException;

public class LiteralInterpreter {

	private TypeFactory typeFactory;

	private ValueFactory valueFactory;

	// private StandardSignedIntegerType SCHAR, SSHORT;

	private StandardSignedIntegerType SINT, SLONG, SLLONG;

	// private StandardUnsignedIntegerType UCHAR, USHORT;

	private StandardUnsignedIntegerType UINT, ULONG, ULLONG;

	private FloatingType FLOAT, DOUBLE, LDOUBLE;

	/** The potential type lists for each kind of suffix. */
	private IntegerType[] noneDec, noneHex, uDec, uHex, lDec, lHex, ulDec,
			ulHex, llDec, llHex, ullDec, ullHex;

	public LiteralInterpreter(TypeFactory typeFactory, ValueFactory valueFactory) {
		this.typeFactory = typeFactory;
		this.valueFactory = valueFactory;
		// SCHAR = typeFactory.signedIntegerType(SignedIntKind.SIGNED_CHAR);
		// SSHORT = typeFactory.signedIntegerType(SignedIntKind.SHORT);
		SINT = typeFactory.signedIntegerType(SignedIntKind.INT);
		SLONG = typeFactory.signedIntegerType(SignedIntKind.LONG);
		SLLONG = typeFactory.signedIntegerType(SignedIntKind.LONG_LONG);
		// UCHAR =
		// typeFactory.unsignedIntegerType(UnsignedIntKind.UNSIGNED_CHAR);
		// USHORT = typeFactory
		// .unsignedIntegerType(UnsignedIntKind.UNSIGNED_SHORT);
		UINT = typeFactory.unsignedIntegerType(UnsignedIntKind.UNSIGNED);
		ULONG = typeFactory.unsignedIntegerType(UnsignedIntKind.UNSIGNED_LONG);
		ULLONG = typeFactory
				.unsignedIntegerType(UnsignedIntKind.UNSIGNED_LONG_LONG);
		FLOAT = (FloatingType) typeFactory.basicType(BasicTypeKind.FLOAT);
		DOUBLE = (FloatingType) typeFactory.basicType(BasicTypeKind.DOUBLE);
		LDOUBLE = (FloatingType) typeFactory
				.basicType(BasicTypeKind.LONG_DOUBLE);
		noneDec = new IntegerType[] { SINT, SLONG, SLLONG };
		noneHex = new IntegerType[] { SINT, UINT, SLONG, ULONG, SLLONG, ULLONG };
		uDec = uHex = new IntegerType[] { UINT, ULONG, ULLONG };
		lDec = new IntegerType[] { SLONG, SLLONG };
		lHex = new IntegerType[] { SLONG, ULONG, SLLONG, ULLONG };
		ulDec = ulHex = new IntegerType[] { ULONG, ULLONG };
		llDec = new IntegerType[] { SLLONG };
		llHex = new IntegerType[] { SLLONG, ULLONG };
		ullDec = ullHex = new IntegerType[] { ULLONG };
	}

	public IntegerConstantNode integerConstant(Source source, String text)
			throws SyntaxException {
		String stripped, suffix;
		int length = text.length();
		IntegerConstantNode node;
		IntegerType type;
		int base;
		IntegerType[] typeList;
		BigInteger bigIntValue;
		IntegerValue value;

		while (length >= 1) {
			char c = text.charAt(length - 1);

			if (c != 'U' && c != 'u' && c != 'l' && c != 'L')
				break;
			length--;
		}
		stripped = text.substring(0, length);
		suffix = text.substring(length);
		try {
			if (stripped.startsWith("0")) {
				if (stripped.startsWith("0x") || stripped.startsWith("0X")) {
					base = 16;
					stripped = stripped.substring(2);
				} else {
					base = 8;
				}
			} else {
				base = 10;
			}
		} catch (NumberFormatException e) {
			throw new SyntaxException("Unable to extract integer value from "
					+ text + ":\n" + e, source);
		}
		bigIntValue = new BigInteger(stripped, base);
		suffix = suffix.toLowerCase();
		// see table on C11 page 64
		if (suffix.isEmpty())
			typeList = (base == 10 ? noneDec : noneHex);
		else if (suffix.equals("u"))
			typeList = (base == 10 ? uDec : uHex);
		else if (suffix.equals("l"))
			typeList = (base == 10 ? lDec : lHex);
		else if (suffix.equals("ul") || suffix.equals("lu"))
			typeList = (base == 10 ? ulDec : ulHex);
		else if (suffix.equals("ll"))
			typeList = (base == 10 ? llDec : llHex);
		else if (suffix.equals("ull") || suffix.equals("llu"))
			typeList = (base == 10 ? ullDec : ullHex);
		else
			throw new SyntaxException("Unknown suffix " + suffix, source);
		type = typeFactory.rangeChoice(bigIntValue, typeList);
		if (type == null)
			throw new SyntaxException(
					"Unable to find integer type to represent constant ",
					source);
		value = valueFactory.integerValue(type, bigIntValue);
		node = new CommonIntegerConstantNode(source, text, value);
		return node;
	}

	public FloatingConstantNode floatingConstant(Source source, String text)
			throws SyntaxException {
		int base, length, expPos, dotPos;
		String stripped, suffix, significand, wholePart, fractionPart, exponent;
		BigInteger wholePartValue, fractionPartValue, exponentValue;
		FloatingType type;
		RealFloatingValue value;

		text = text.toLowerCase();
		length = text.length();
		while (length >= 1) {
			char c = text.charAt(length - 1);

			if (c != 'l' && c != 'f')
				break;
			length--;
		}
		stripped = text.substring(0, length);
		suffix = text.substring(length);
		if (stripped.startsWith("0x")) {
			base = 16;
			stripped = stripped.substring(2);
		} else {
			base = 10;
		}
		expPos = stripped.indexOf(base == 10 ? 'e' : 'p');
		if (expPos >= 0) {
			significand = stripped.substring(0, expPos);
			exponent = stripped.substring(expPos + 1);
		} else {
			significand = stripped;
			exponent = "";
		}
		dotPos = significand.indexOf('.');
		if (dotPos >= 0) {
			wholePart = significand.substring(0, dotPos);
			fractionPart = significand.substring(dotPos + 1);
		} else {
			wholePart = significand;
			fractionPart = "";
		}
		if (suffix.isEmpty())
			type = DOUBLE;
		else if ("f".equals(suffix))
			type = FLOAT;
		else if ("l".equals(suffix))
			type = LDOUBLE;
		else
			throw new SyntaxException("Unknown floating suffix: " + suffix,
					source);
		if (wholePart.isEmpty())
			wholePartValue = BigInteger.ZERO;
		else
			wholePartValue = new BigInteger(wholePart, base);
		if (fractionPart.isEmpty())
			fractionPartValue = BigInteger.ZERO;
		else
			fractionPartValue = new BigInteger(fractionPart, base);
		if (exponent.isEmpty())
			exponentValue = BigInteger.ZERO;
		else
			exponentValue = new BigInteger(exponent, 10);
		value = valueFactory.realFloatingValue(type, base, wholePartValue,
				fractionPartValue, fractionPart.length(), exponentValue);
		return new CommonFloatingConstantNode(source, text, wholePart,
				fractionPart, exponent, value);
	}

}