/**
* Copyright (C) 2010 dennis zhuang (killme2008@gmail.com)
*
* This library 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 2.1 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 program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
**/
package com.googlecode.aviator.lexer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.junit.Test;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Options;
import com.googlecode.aviator.exception.CompileExpressionErrorException;
import com.googlecode.aviator.lexer.token.Token;
import com.googlecode.aviator.lexer.token.Token.TokenType;
public class ExpressionLexerUnitTest {
private ExpressionLexer lexer;
@Test
public void testSimpleExpression() {
this.lexer = new ExpressionLexer("1+2");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(1, token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(1, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2, token.getValue(null));
assertEquals(2, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test
public void testParseBigNumber() {
this.lexer = new ExpressionLexer("92233720368547758071");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigInteger("92233720368547758071"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseHexNumber() {
this.lexer = new ExpressionLexer("0X0a2B");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2603, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseBigInteger() {
this.lexer = new ExpressionLexer("3N");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigInteger("3"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation1() {
this.lexer = new ExpressionLexer("3e2");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(300.0, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotationBiggerSmaller() {
this.lexer = new ExpressionLexer("3e10");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3e10, token.getValue(null));
assertEquals(0, token.getStartIndex());
this.lexer = new ExpressionLexer("3e100");
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3e100, token.getValue(null));
assertEquals(0, token.getStartIndex());
this.lexer = new ExpressionLexer("3e-100");
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3e-100, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation2() {
this.lexer = new ExpressionLexer("3E2");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(300.0, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation3() {
this.lexer = new ExpressionLexer("3e-1");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(0.3, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation4() {
this.lexer = new ExpressionLexer("3E-2");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(0.03, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation5() {
this.lexer = new ExpressionLexer("3E2M");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigDecimal("300"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseScientificNotation6() {
this.lexer = new ExpressionLexer("3e-1M");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigDecimal("0.3"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test(expected = CompileExpressionErrorException.class)
public void testParseScientificNotation7() {
this.lexer = new ExpressionLexer("3e3N");
Token<?> token = this.lexer.scan();
}
@Test
public void testParseScientificNotation8() {
this.lexer = new ExpressionLexer("2.3456e3");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2345.6, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test(expected = NumberFormatException.class)
public void testIllegalNumber1() {
this.lexer = new ExpressionLexer("3EM+2");
while (this.lexer.scan() != null) {
;
}
}
@Test
public void testParseBigDecimal() {
this.lexer = new ExpressionLexer("3.2M");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigDecimal("3.2"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testParseNumbers() {
this.lexer = new ExpressionLexer("3N .2M 1 2.3 4.33M");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigInteger("3"), token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigDecimal("0.2"), token.getValue(null));
assertEquals(3, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(1, token.getValue(null));
assertEquals(7, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2.3, token.getValue(null));
assertEquals(9, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(new BigDecimal("4.33"), token.getValue(null));
assertEquals(14, token.getStartIndex());
}
@Test
public void testParseDoubleAsDecimal() {
try {
AviatorEvaluator.setOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL, true);
this.lexer = new ExpressionLexer("3.2");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertTrue(token.getValue(null) instanceof BigDecimal);
assertEquals(new BigDecimal("3.2"), token.getValue(null));
assertEquals(0, token.getStartIndex());
}
finally {
AviatorEvaluator.setOption(Options.ALWAYS_USE_DOUBLE_AS_DECIMAL, false);
}
}
@Test
public void testParseLikeHexNumber() {
this.lexer = new ExpressionLexer("0344");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(344, token.getValue(null));
assertEquals(0, token.getStartIndex());
}
@Test
public void testSimpleExpression_WithHexNumber() {
this.lexer = new ExpressionLexer("3+0xAF");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3, token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(1, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(175, token.getValue(null));
assertEquals(2, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test
public void testSimpleExpression_WithSpace() {
this.lexer = new ExpressionLexer(" 1 + 2 ");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(1, token.getValue(null));
assertEquals(1, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(3, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2, token.getValue(null));
assertEquals(5, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test
public void testExpression_WithDouble() {
this.lexer = new ExpressionLexer("3.0+4-5.9");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3.0, token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(3, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(4, token.getValue(null));
assertEquals(4, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('-', token.getValue(null));
assertEquals(5, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(5.9, token.getValue(null));
assertEquals(6, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test(expected = CompileExpressionErrorException.class)
public void testExpression_WithIllegalDouble() {
this.lexer = new ExpressionLexer("3.0+4-5.9.2");
while (this.lexer.scan() != null) {
;
}
}
@Test
public void testExpression_True_False() {
this.lexer = new ExpressionLexer("true");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertTrue((Boolean) token.getValue(null));
assertNull(this.lexer.scan());
this.lexer = new ExpressionLexer("false");
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertFalse((Boolean) token.getValue(null));
assertNull(this.lexer.scan());
}
@Test
public void testExpression_Logic_Join() {
this.lexer = new ExpressionLexer("a || c ");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("a", token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('|', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('|', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("c", token.getValue(null));
assertNull(this.lexer.scan());
}
@Test
public void testExpression_Eq() {
this.lexer = new ExpressionLexer("a ==c ");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("a", token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('=', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('=', token.getValue(null));
token = this.lexer.scan();
assertEquals("c", token.getValue(null));
}
@Test
public void testExpression_Not() {
this.lexer = new ExpressionLexer("!(3<=1)");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('!', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('(', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3, token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('<', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('=', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(1, token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals(')', token.getValue(null));
assertNull(this.lexer.scan());
}
@Test
public void testBlank_SpaceExpression() {
this.lexer = new ExpressionLexer("");
assertNull(this.lexer.scan());
this.lexer = new ExpressionLexer(" ");
assertNull(this.lexer.scan());
this.lexer = new ExpressionLexer("\t");
assertNull(this.lexer.scan());
this.lexer = new ExpressionLexer("\t \t");
assertNull(this.lexer.scan());
}
@Test
public void testExpression_Neg() {
this.lexer = new ExpressionLexer("-10.3");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('-', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(10.3, token.getValue(null));
}
@Test
public void testExpression_Logic_And() {
this.lexer = new ExpressionLexer("a==3 && false");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("a", token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('=', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('=', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(3, token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('&', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('&', token.getValue(null));
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertFalse((Boolean) token.getValue(null));
assertNull(this.lexer.scan());
}
@Test
public void testExpression_WithString() {
this.lexer = new ExpressionLexer("'hello world'");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.String, token.getType());
assertEquals("hello world", token.getValue(null));
assertEquals(0, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test
public void testExpression_WithNestedString() {
this.lexer = new ExpressionLexer("'hello \"good\" world'");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.String, token.getType());
assertEquals("hello \"good\" world", token.getValue(null));
assertEquals(0, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test(expected = CompileExpressionErrorException.class)
public void testExpression_WithIllegalString() {
this.lexer = new ExpressionLexer("'hello \" world");
this.lexer.scan();
}
@Test
public void testExpressionHasPattern() {
this.lexer = new ExpressionLexer("/a\\.f\\d+/");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("/", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("a", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("\\", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(".", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("f", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("\\", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("d", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("+", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("/", token.getLexeme());
assertNull(this.lexer.scan());
}
@Test
public void testExpressionHasPattern2() {
this.lexer = new ExpressionLexer("/\\//");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("/", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("\\", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("/", token.getLexeme());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals("/", token.getLexeme());
token = this.lexer.scan();
assertNull(this.lexer.scan());
}
@Test
public void testExpressionWithParen() {
this.lexer = new ExpressionLexer("2.0+(2+2)*99");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2.0, token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(3, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('(', token.getValue(null));
assertEquals(4, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2, token.getValue(null));
assertEquals(5, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(6, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(2, token.getValue(null));
assertEquals(7, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals(')', token.getValue(null));
assertEquals(8, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('*', token.getValue(null));
assertEquals(9, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Number, token.getType());
assertEquals(99, token.getValue(null));
assertEquals(10, token.getStartIndex());
assertNull(this.lexer.scan());
}
@Test
public void testNotAnsylyse() {
this.lexer = new ExpressionLexer("a + b *d+'hello\n'");
Token<?> token = this.lexer.scan();
assertEquals(TokenType.Variable, token.getType());
assertEquals("a", token.getValue(null));
assertEquals(0, token.getStartIndex());
token = this.lexer.scan();
assertEquals(TokenType.Char, token.getType());
assertEquals('+', token.getValue(null));
assertEquals(2, token.getStartIndex());
token = this.lexer.scan(false);
assertEquals(TokenType.Char, token.getType());
assertEquals(' ', token.getValue(null));
assertEquals(3, token.getStartIndex());
token = this.lexer.scan(false);
assertEquals(TokenType.Char, token.getType());
assertEquals('b', token.getValue(null));
assertEquals(4, token.getStartIndex());
}
@Test(expected = CompileExpressionErrorException.class)
public void testScanHasLine() {
this.lexer = new ExpressionLexer("4+5>\n5");
while (this.lexer.scan() != null) {
;
}
}
@Test
public void testPushBack() {
this.lexer = new ExpressionLexer("13+100");
Token<?> token = this.lexer.scan();
assertEquals("13", token.getLexeme());
this.lexer.pushback(token);
token = this.lexer.scan();
assertEquals("13", token.getLexeme());
token = this.lexer.scan();
assertEquals("+", token.getLexeme());
this.lexer.pushback(token);
token = this.lexer.scan();
assertEquals("+", token.getLexeme());
token = this.lexer.scan();
assertEquals("100", token.getLexeme());
assertNull(this.lexer.scan());
}
}