use of com.googlecode.aviator.lexer.token.NumberToken in project aviatorscript by killme2008.
the class OptimizeCodeGenerator method getTokenFromOperand.
/**
* Get token from executing result
*
* @param operand
* @return
*/
private Token<?> getTokenFromOperand(final Token<?> operatorToken, final AviatorObject operand) {
Token<?> token = null;
switch(operand.getAviatorType()) {
case JavaType:
if (operand instanceof AviatorRuntimeJavaType) {
Object val = operand.getValue(null);
if (val == null) {
token = Variable.NIL;
} else if (val instanceof Number) {
token = new NumberToken((Number) val, val.toString(), operatorToken.getLineNo(), operatorToken.getStartIndex());
} else if (val instanceof String || val instanceof Character) {
String s = val.toString();
token = new StringToken(s, operatorToken.getLineNo(), operatorToken.getStartIndex()).withMeta(Constants.INTER_META, s.contains("#"));
} else if (val instanceof Pattern) {
token = new PatternToken(((Pattern) val).pattern(), operatorToken.getLineNo(), operatorToken.getStartIndex());
} else if (val instanceof Boolean) {
token = (boolean) val ? Variable.TRUE : Variable.FALSE;
} else {
throw new CompileExpressionErrorException("Invalid operand:" + operand.desc(null));
}
} else {
throw new CompileExpressionErrorException("Invalid operand:" + operand.desc(null));
}
break;
case Boolean:
token = operand.booleanValue(null) ? Variable.TRUE : Variable.FALSE;
break;
case Nil:
token = Variable.NIL;
break;
case BigInt:
case Decimal:
case Double:
case Long:
final Number value = (Number) operand.getValue(null);
token = new NumberToken(value, value.toString(), operatorToken.getLineNo(), operatorToken.getStartIndex());
break;
case String:
final String str = (String) operand.getValue(null);
token = new StringToken(str, operatorToken.getLineNo(), operatorToken.getStartIndex());
break;
case Pattern:
token = new PatternToken(((AviatorPattern) operand).getPattern().pattern(), operatorToken.getLineNo(), operatorToken.getStartIndex());
break;
}
return token;
}
use of com.googlecode.aviator.lexer.token.NumberToken in project aviatorscript by killme2008.
the class OptimizeCodeGenerator method getAviatorObjectFromToken.
private AviatorObject getAviatorObjectFromToken(final Token<?> lookhead) {
AviatorObject result = null;
switch(lookhead.getType()) {
case Number:
// load numbers
NumberToken numberToken = (NumberToken) lookhead;
Number num = numberToken.getNumber();
result = AviatorNumber.valueOf(num);
break;
case String:
// load string
result = new AviatorString((String) lookhead.getValue(null), true, true, lookhead.getLineNo());
break;
case Pattern:
// load pattern
result = new AviatorPattern((String) lookhead.getValue(null));
break;
case Variable:
if (lookhead == Variable.TRUE) {
result = AviatorBoolean.TRUE;
} else if (lookhead == Variable.FALSE) {
result = AviatorBoolean.FALSE;
} else if (lookhead == Variable.NIL) {
result = AviatorNil.NIL;
}
break;
case Char:
result = new AviatorString(String.valueOf(lookhead.getValue(null)), true, true, lookhead.getLineNo());
break;
}
return result;
}
use of com.googlecode.aviator.lexer.token.NumberToken in project aviatorscript by killme2008.
the class ExpressionLexer method scan.
public Token<?> scan(final boolean analyse) {
// If buffer is not empty,return
if (this.tokenBuffer != null && !this.tokenBuffer.isEmpty()) {
return this.tokenBuffer.pop();
}
// Skip white space or line
for (; ; nextChar()) {
if (this.peek == CharacterIterator.DONE) {
return null;
}
if (analyse) {
if (this.peek == ' ' || this.peek == '\t' || this.peek == '\r' || this.peek == '\n') {
if (this.peek == '\n') {
this.lineNo++;
}
continue;
}
break;
} else {
char ch = this.peek;
int index = this.iterator.getIndex();
nextChar();
return new CharToken(ch, this.lineNo, index);
}
}
// if it is a hex digit
if (Character.isDigit(this.peek) && this.peek == '0') {
nextChar();
if (this.peek == 'x' || this.peek == 'X') {
nextChar();
StringBuilder sb = new StringBuilder();
int startIndex = this.iterator.getIndex() - 2;
long value = 0L;
do {
sb.append(this.peek);
value = 16 * value + Character.digit(this.peek, 16);
nextChar();
} while (isValidHexChar(this.peek));
return new NumberToken(value, sb.toString(), this.lineNo, startIndex);
} else {
prevChar();
}
}
// If it is a digit
if (Character.isDigit(this.peek) || this.peek == '.') {
StringBuilder sb = new StringBuilder();
int startIndex = this.iterator.getIndex();
long lval = 0L;
double dval = 0d;
boolean hasDot = false;
double d = 10.0;
boolean isBigInt = false;
boolean isBigDecimal = false;
boolean scientificNotation = false;
boolean negExp = false;
boolean isOverflow = false;
do {
sb.append(this.peek);
if (this.peek == '.') {
if (scientificNotation) {
throw new CompileExpressionErrorException("Illegal number " + sb + " at " + this.iterator.getIndex());
}
if (hasDot) {
throw new CompileExpressionErrorException("Illegal Number " + sb + " at " + this.iterator.getIndex());
} else {
hasDot = true;
nextChar();
}
} else if (this.peek == 'N') {
// big integer
if (hasDot) {
throw new CompileExpressionErrorException("Illegal number " + sb + " at " + this.iterator.getIndex());
}
isBigInt = true;
nextChar();
break;
} else if (this.peek == 'M') {
isBigDecimal = true;
nextChar();
break;
} else if (this.peek == 'e' || this.peek == 'E') {
if (scientificNotation) {
throw new CompileExpressionErrorException("Illegal number " + sb + " at " + this.iterator.getIndex());
}
scientificNotation = true;
nextChar();
if (this.peek == '-') {
negExp = true;
sb.append(this.peek);
nextChar();
}
} else {
int digit = Character.digit(this.peek, 10);
if (scientificNotation) {
int n = digit;
nextChar();
while (Character.isDigit(this.peek)) {
sb.append(this.peek);
n = 10 * n + Character.digit(this.peek, 10);
nextChar();
}
while (n-- > 0) {
if (negExp) {
dval = dval / 10;
} else {
dval = 10 * dval;
}
}
hasDot = true;
} else if (hasDot) {
dval = dval + digit / d;
d = d * 10;
nextChar();
} else {
if (!isOverflow && (lval > OVERFLOW_FLAG || (lval == OVERFLOW_FLAG && digit > OVERFLOW_SINGLE))) {
isOverflow = true;
}
lval = 10 * lval + digit;
dval = 10 * dval + digit;
nextChar();
}
}
} while (Character.isDigit(this.peek) || this.peek == '.' || this.peek == 'E' || this.peek == 'e' || this.peek == 'M' || this.peek == 'N');
Number value;
if (isBigDecimal) {
value = new BigDecimal(getBigNumberLexeme(sb), this.mathContext);
} else if (isBigInt) {
value = new BigInteger(getBigNumberLexeme(sb));
} else if (hasDot) {
if (this.parseFloatIntoDecimal && sb.length() > 1) {
value = new BigDecimal(sb.toString(), this.mathContext);
} else if (sb.length() == 1) {
// only have a dot character.
return new CharToken('.', this.lineNo, startIndex);
} else {
value = dval;
}
} else {
if (this.parseIntegralNumberIntoDecimal) {
// we make integral number as a BigDecimal.
value = new BigDecimal(sb.toString(), this.mathContext);
} else {
// The long value is overflow, we should prompt it to be a BigInteger.
if (isOverflow) {
value = new BigInteger(sb.toString());
} else {
value = lval;
}
}
}
String lexeme = sb.toString();
if (isBigDecimal || isBigInt) {
lexeme = lexeme.substring(0, lexeme.length() - 1);
}
return new NumberToken(value, lexeme, this.lineNo, startIndex);
}
// It is a variable
if (this.peek == '#') {
int startIndex = this.iterator.getIndex();
// skip '#'
nextChar();
boolean hasBackquote = false;
if (this.peek == '#') {
// ## comments
while (this.peek != CharacterIterator.DONE && this.peek != '\n') {
nextChar();
}
return this.scan(analyse);
} else if (this.peek == '`') {
hasBackquote = true;
nextChar();
}
StringBuilder sb = new StringBuilder();
if (hasBackquote) {
while (this.peek != '`') {
if (this.peek == CharacterIterator.DONE) {
throw new CompileExpressionErrorException("EOF while reading string at index: " + this.iterator.getIndex());
}
sb.append(this.peek);
nextChar();
}
// skip '`'
nextChar();
} else {
while (Character.isJavaIdentifierPart(this.peek) || this.peek == '.' || this.peek == '[' || this.peek == ']') {
sb.append(this.peek);
nextChar();
}
}
String lexeme = sb.toString();
if (lexeme.isEmpty()) {
throw new ExpressionSyntaxErrorException("Blank variable name after '#'");
}
Variable variable = new Variable(lexeme, this.lineNo, startIndex);
variable.setQuote(true);
return this.symbolTable.reserve(variable);
}
if (Character.isJavaIdentifierStart(this.peek)) {
int startIndex = this.iterator.getIndex();
StringBuilder sb = new StringBuilder();
do {
sb.append(this.peek);
nextChar();
} while (Character.isJavaIdentifierPart(this.peek) || this.peek == '.');
String lexeme = sb.toString();
Variable variable = new Variable(lexeme, this.lineNo, startIndex);
return this.symbolTable.reserve(variable);
}
if (isBinaryOP(this.peek)) {
CharToken opToken = new CharToken(this.peek, this.lineNo, this.iterator.getIndex());
nextChar();
return opToken;
}
// String
if (this.peek == '"' || this.peek == '\'') {
char left = this.peek;
int startIndex = this.iterator.getIndex();
StringBuilder sb = new StringBuilder();
boolean hasInterpolation = false;
// char prev = this.peek;
while ((this.peek = this.iterator.next()) != left) {
// It's not accurate,but acceptable.
if (this.peek == '#' && !hasInterpolation) {
hasInterpolation = true;
}
if (this.peek == '\\') {
// escape
nextChar();
if (this.peek == CharacterIterator.DONE) {
throw new CompileExpressionErrorException("EOF while reading string at index: " + this.iterator.getIndex());
}
if (this.peek == left) {
sb.append(this.peek);
continue;
}
switch(this.peek) {
case 't':
this.peek = '\t';
break;
case 'r':
this.peek = '\r';
break;
case 'n':
this.peek = '\n';
break;
case '\\':
break;
case 'b':
this.peek = '\b';
break;
case 'f':
this.peek = '\f';
break;
case '#':
hasInterpolation = hasInterpolation || true;
if (this.instance.isFeatureEnabled(Feature.StringInterpolation)) {
sb.append('\\');
this.peek = '#';
break;
}
default:
{
throw new CompileExpressionErrorException("Unsupported escape character: \\" + this.peek);
}
}
}
if (this.peek == CharacterIterator.DONE) {
throw new CompileExpressionErrorException("EOF while reading string at index: " + this.iterator.getIndex());
}
sb.append(this.peek);
}
nextChar();
return new StringToken(sb.toString(), this.lineNo, startIndex).withMeta(Constants.INTER_META, hasInterpolation);
}
Token<Character> token = new CharToken(this.peek, this.lineNo, this.iterator.getIndex());
nextChar();
return token;
}
use of com.googlecode.aviator.lexer.token.NumberToken in project aviatorscript by killme2008.
the class LoadIR method evalWithoutDispatch.
public void evalWithoutDispatch(final InterpretContext context) {
if (this.token == null) {
return;
}
if (this.inConstantPool) {
final AviatorObject constant = context.loadConstant(this.token);
assert (constant != null);
context.push(constant);
return;
}
// load token to stack
switch(this.token.getType()) {
case Number:
// load numbers
NumberToken numberToken = (NumberToken) this.token;
Number number = numberToken.getNumber();
if (TypeUtils.isBigInt(number)) {
context.push(AviatorBigInt.valueOf(this.token.getLexeme()));
} else if (TypeUtils.isDecimal(number)) {
context.push(AviatorDecimal.valueOf(context.getEnv(), this.token.getLexeme()));
} else if (TypeUtils.isDouble(number)) {
context.push(AviatorDouble.valueOf(number.doubleValue()));
} else {
context.push(AviatorLong.valueOf(number.longValue()));
}
break;
case String:
context.push(new AviatorString((String) this.token.getValue(null), true, this.token.getMeta(Constants.INTER_META, true), this.token.getLineNo()));
break;
case Pattern:
context.push(new AviatorPattern((String) this.token.getValue(null)));
break;
case Variable:
if (this.token == Variable.TRUE) {
context.push(AviatorBoolean.TRUE);
} else if (this.token == Variable.FALSE) {
context.push(AviatorBoolean.FALSE);
} else if (this.token == Variable.NIL) {
context.push(AviatorNil.NIL);
} else {
AviatorJavaType var;
if (this.meta != null) {
var = context.loadVar(this.meta);
assert (var != null);
} else {
var = new AviatorJavaType(this.token.getLexeme());
}
context.push(var);
}
break;
default:
throw new ExpressionRuntimeException("Can't load " + this.token);
}
}
use of com.googlecode.aviator.lexer.token.NumberToken in project aviatorscript by killme2008.
the class ASMCodeGeneratorUnitTest method testOnBitNot2.
@Test
public void testOnBitNot2() throws Exception {
this.codeGenerator.onConstant(new NumberToken(3L, "3"));
this.codeGenerator.onBitNot(null);
Object result = eval(new HashMap<String, Object>());
assertEquals(-4L, result);
}
Aggregations