/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.dmn.feel.parser.feel11;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.Test;
import org.kie.dmn.feel.lang.ast.*;
import org.kie.dmn.feel.util.Msg;
import java.util.Collections;
import java.util.Map;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
public class FEELParserTest {
@Test
public void testIntegerLiteral() {
String inputExpression = "10";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( NumberNode.class ) ) );
assertLocation( inputExpression, number );
}
@Test
public void testNegativeIntegerLiteral() {
String inputExpression = "-10";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( SignedUnaryNode.class ) ) );
assertLocation( inputExpression, number );
SignedUnaryNode sun = (SignedUnaryNode) number;
assertThat( sun.getSign(), is( SignedUnaryNode.Sign.NEGATIVE ) );
assertThat( sun.getExpression(), is( instanceOf( NumberNode.class ) ) );
assertThat( sun.getExpression().getText(), is( "10" ) );
}
@Test
public void testPositiveIntegerLiteral() {
String inputExpression = "+10";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( SignedUnaryNode.class ) ) );
assertLocation( inputExpression, number );
SignedUnaryNode sun = (SignedUnaryNode) number;
assertThat( sun.getSign(), is( SignedUnaryNode.Sign.POSITIVE ) );
assertThat( sun.getExpression(), is( instanceOf( NumberNode.class ) ) );
assertThat( sun.getExpression().getText(), is( "10" ) );
}
@Test
public void testFloatLiteral() {
String inputExpression = "10.5";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( NumberNode.class ) ) );
assertLocation( inputExpression, number );
}
@Test
public void testNegativeFloatLiteral() {
String inputExpression = "-10.5";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( SignedUnaryNode.class ) ) );
assertLocation( inputExpression, number );
SignedUnaryNode sun = (SignedUnaryNode) number;
assertThat( sun.getSign(), is( SignedUnaryNode.Sign.NEGATIVE ) );
assertThat( sun.getExpression(), is( instanceOf( NumberNode.class ) ) );
assertThat( sun.getExpression().getText(), is( "10.5" ) );
}
@Test
public void testPositiveFloatLiteral() {
String inputExpression = "+10.5";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( SignedUnaryNode.class ) ) );
assertLocation( inputExpression, number );
SignedUnaryNode sun = (SignedUnaryNode) number;
assertThat( sun.getSign(), is( SignedUnaryNode.Sign.POSITIVE ) );
assertThat( sun.getExpression(), is( instanceOf( NumberNode.class ) ) );
assertThat( sun.getExpression().getText(), is( "10.5" ) );
}
@Test
public void testBooleanTrueLiteral() {
String inputExpression = "true";
BaseNode bool = parse( inputExpression );
assertThat( bool, is( instanceOf( BooleanNode.class ) ) );
assertLocation( inputExpression, bool );
}
@Test
public void testBooleanFalseLiteral() {
String inputExpression = "false";
BaseNode bool = parse( inputExpression );
assertThat( bool, is( instanceOf( BooleanNode.class ) ) );
assertLocation( inputExpression, bool );
}
@Test
public void testNullLiteral() {
String inputExpression = "null";
BaseNode nullLit = parse( inputExpression );
assertThat( nullLit, is( instanceOf( NullNode.class ) ) );
assertLocation( inputExpression, nullLit );
}
@Test
public void testStringLiteral() {
String inputExpression = "\"some string\"";
BaseNode nullLit = parse( inputExpression );
assertThat( nullLit, is( instanceOf( StringNode.class ) ) );
assertLocation( inputExpression, nullLit );
}
@Test
public void testNameReference() {
String inputExpression = "someSimpleName";
BaseNode nullLit = parse( inputExpression );
assertThat( nullLit, is( instanceOf( NameRefNode.class ) ) );
assertLocation( inputExpression, nullLit );
}
@Test
public void testParensWithLiteral() {
String inputExpression = "(10.5 )";
BaseNode number = parse( inputExpression );
assertThat( number, is( instanceOf( NumberNode.class ) ) );
assertThat( number.getText(), is( "10.5" ) );
}
@Test
public void testLogicalNegation() {
String inputExpression = "not ( true )";
BaseNode neg = parse( inputExpression );
assertThat( neg, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( neg.getText(), is( "not ( true )" ) );
FunctionInvocationNode not = (FunctionInvocationNode) neg;
assertThat( not.getParams().getElements().get( 0 ), is( instanceOf( BooleanNode.class ) ) );
assertThat( not.getParams().getElements().get( 0 ).getText(), is( "true" ) );
}
@Test
public void testMultiplication() {
String inputExpression = "10 * x";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode mult = (InfixOpNode) infix;
assertThat( mult.getLeft(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "10" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NameRefNode.class ) ) );
assertThat( mult.getRight().getText(), is( "x" ) );
}
@Test
public void testDivision() {
String inputExpression = "y / 5 * ( x )";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode mult = (InfixOpNode) infix;
assertThat( mult.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "y / 5" ) );
InfixOpNode div = (InfixOpNode) mult.getLeft();
assertThat( div.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( div.getLeft().getText(), is( "y" ) );
assertThat( div.getOperator(), is( InfixOpNode.InfixOperator.DIV ) );
assertThat( div.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( div.getRight().getText(), is( "5" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NameRefNode.class ) ) );
assertThat( mult.getRight().getText(), is( "x" ) );
}
@Test
public void testPower1() {
String inputExpression = "y * 5 ** 3";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode mult = (InfixOpNode) infix;
assertThat( mult.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "y" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( mult.getRight().getText(), is( "5 ** 3" ) );
InfixOpNode exp = (InfixOpNode) mult.getRight();
assertThat( exp.getLeft(), is( instanceOf( NumberNode.class ) ) );
assertThat( exp.getLeft().getText(), is( "5" ) );
assertThat( exp.getOperator(), is( InfixOpNode.InfixOperator.POW ) );
assertThat( exp.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( exp.getRight().getText(), is( "3" ) );
}
@Test
public void testPower2() {
String inputExpression = "(y * 5) ** 3";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode exp = (InfixOpNode) infix;
assertThat( exp.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( exp.getLeft().getText(), is( "y * 5" ) );
assertThat( exp.getOperator(), is( InfixOpNode.InfixOperator.POW ) );
assertThat( exp.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( exp.getRight().getText(), is( "3" ) );
InfixOpNode mult = (InfixOpNode) exp.getLeft();
assertThat( mult.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "y" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getRight().getText(), is( "5" ) );
}
@Test
public void testPower3() {
String inputExpression = "y ** 5 * 3";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode mult = (InfixOpNode) infix;
assertThat( mult.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "y ** 5" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getRight().getText(), is( "3" ) );
InfixOpNode exp = (InfixOpNode) mult.getLeft();
assertThat( exp.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( exp.getLeft().getText(), is( "y" ) );
assertThat( exp.getOperator(), is( InfixOpNode.InfixOperator.POW ) );
assertThat( exp.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( exp.getRight().getText(), is( "5" ) );
}
@Test
public void testPower4() {
String inputExpression = "y ** ( 5 * 3 )";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode exp = (InfixOpNode) infix;
assertThat( exp.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( exp.getLeft().getText(), is( "y" ) );
assertThat( exp.getOperator(), is( InfixOpNode.InfixOperator.POW ) );
assertThat( exp.getRight(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( exp.getRight().getText(), is( "5 * 3" ) );
InfixOpNode mult = (InfixOpNode) exp.getRight();
assertThat( mult.getLeft(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "5" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getRight().getText(), is( "3" ) );
}
@Test
public void testAdd1() {
String inputExpression = "y + 5 * 3";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode add = (InfixOpNode) infix;
assertThat( add.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( add.getLeft().getText(), is( "y" ) );
assertThat( add.getOperator(), is( InfixOpNode.InfixOperator.ADD ) );
assertThat( add.getRight(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( add.getRight().getText(), is( "5 * 3" ) );
InfixOpNode mult = (InfixOpNode) add.getRight();
assertThat( mult.getLeft(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "5" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.MULT ) );
assertThat( mult.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getRight().getText(), is( "3" ) );
}
@Test
public void testSub1() {
String inputExpression = "(y - 5) ** 3";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode sub = (InfixOpNode) infix;
assertThat( sub.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( sub.getLeft().getText(), is( "y - 5" ) );
assertThat( sub.getOperator(), is( InfixOpNode.InfixOperator.POW ) );
assertThat( sub.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( sub.getRight().getText(), is( "3" ) );
InfixOpNode mult = (InfixOpNode) sub.getLeft();
assertThat( mult.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( mult.getLeft().getText(), is( "y" ) );
assertThat( mult.getOperator(), is( InfixOpNode.InfixOperator.SUB ) );
assertThat( mult.getRight(), is( instanceOf( NumberNode.class ) ) );
assertThat( mult.getRight().getText(), is( "5" ) );
}
@Test
public void testBetween() {
String inputExpression = "x between 10+y and 3**z";
BaseNode between = parse( inputExpression );
assertThat( between, is( instanceOf( BetweenNode.class ) ) );
assertThat( between.getText(), is( inputExpression ) );
BetweenNode btw = (BetweenNode) between;
assertThat( btw.getValue(), is( instanceOf( NameRefNode.class ) ) );
assertThat( btw.getValue().getText(), is( "x" ) );
assertThat( btw.getStart(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( btw.getStart().getText(), is( "10+y" ) );
assertThat( btw.getEnd(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( btw.getEnd().getText(), is( "3**z" ) );
}
@Test
public void testInValueList() {
String inputExpression = "x / 4 in ( 10+y, true, 80, someVar )";
BaseNode inNode = parse( inputExpression );
assertThat( inNode, is( instanceOf( InNode.class ) ) );
assertThat( inNode.getText(), is( inputExpression ) );
InNode in = (InNode) inNode;
assertThat( in.getValue(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( in.getValue().getText(), is( "x / 4" ) );
assertThat( in.getExprs(), is( instanceOf( ListNode.class ) ) );
assertThat( in.getExprs().getText(), is( "10+y, true, 80, someVar" ) );
ListNode list = (ListNode) in.getExprs();
assertThat( list.getElements().get( 0 ), is( instanceOf( InfixOpNode.class ) ) );
assertThat( list.getElements().get( 1 ), is( instanceOf( BooleanNode.class ) ) );
assertThat( list.getElements().get( 2 ), is( instanceOf( NumberNode.class ) ) );
assertThat( list.getElements().get( 3 ), is( instanceOf( NameRefNode.class ) ) );
}
@Test
public void testInUnaryTestList() {
String inputExpression = "x ** y in ( <=1000, >t, null, (2000..z[, ]z..2000], [(10+5)..(a*b)) )";
BaseNode inNode = parse( inputExpression );
assertThat( inNode, is( instanceOf( InNode.class ) ) );
assertThat( inNode.getText(), is( inputExpression ) );
InNode in = (InNode) inNode;
assertThat( in.getValue(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( in.getValue().getText(), is( "x ** y" ) );
assertThat( in.getExprs(), is( instanceOf( ListNode.class ) ) );
assertThat( in.getExprs().getText(), is( "<=1000, >t, null, (2000..z[, ]z..2000], [(10+5)..(a*b))" ) );
ListNode list = (ListNode) in.getExprs();
assertThat( list.getElements().get( 0 ), is( instanceOf( UnaryTestNode.class ) ) );
assertThat( list.getElements().get( 0 ).getText(), is( "<=1000" ) );
assertThat( list.getElements().get( 1 ), is( instanceOf( UnaryTestNode.class ) ) );
assertThat( list.getElements().get( 1 ).getText(), is( ">t" ) );
assertThat( list.getElements().get( 2 ), is( instanceOf( NullNode.class ) ) );
assertThat( list.getElements().get( 2 ).getText(), is( "null" ) );
assertThat( list.getElements().get( 3 ), is( instanceOf( RangeNode.class ) ) );
RangeNode interval = (RangeNode) list.getElements().get( 3 );
assertThat( interval.getText(), is( "(2000..z[") );
assertThat( interval.getLowerBound(), is( RangeNode.IntervalBoundary.OPEN ) );
assertThat( interval.getUpperBound(), is( RangeNode.IntervalBoundary.OPEN ) );
assertThat( interval.getStart(), is( instanceOf( NumberNode.class ) ) );
assertThat( interval.getEnd(), is( instanceOf( NameRefNode.class ) ) );
assertThat( list.getElements().get( 4 ), is( instanceOf( RangeNode.class ) ) );
interval = (RangeNode) list.getElements().get( 4 );
assertThat( interval.getText(), is( "]z..2000]") );
assertThat( interval.getLowerBound(), is( RangeNode.IntervalBoundary.OPEN ) );
assertThat( interval.getUpperBound(), is( RangeNode.IntervalBoundary.CLOSED ) );
assertThat( interval.getStart(), is( instanceOf( NameRefNode.class ) ) );
assertThat( interval.getEnd(), is( instanceOf( NumberNode.class ) ) );
assertThat( list.getElements().get( 5 ), is( instanceOf( RangeNode.class ) ) );
interval = (RangeNode) list.getElements().get( 5 );
assertThat( interval.getText(), is( "[(10+5)..(a*b))") );
assertThat( interval.getLowerBound(), is( RangeNode.IntervalBoundary.CLOSED ) );
assertThat( interval.getUpperBound(), is( RangeNode.IntervalBoundary.OPEN ) );
assertThat( interval.getStart(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( interval.getEnd(), is( instanceOf( InfixOpNode.class ) ) );
}
@Test
public void testInUnaryTest() {
String inputExpression = "x - y in [(10+5)..(a*b))";
BaseNode inNode = parse( inputExpression );
assertThat( inNode, is( instanceOf( InNode.class ) ) );
assertThat( inNode.getText(), is( inputExpression ) );
InNode in = (InNode) inNode;
assertThat( in.getValue(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( in.getValue().getText(), is( "x - y" ) );
assertThat( in.getExprs(), is( instanceOf( RangeNode.class ) ) );
assertThat( in.getExprs().getText(), is( "[(10+5)..(a*b))" ) );
}
@Test
public void testComparisonInFixOp() {
String inputExpression = "foo >= bar * 10";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode in = (InfixOpNode) infix;
assertThat( in.getLeft(), is( instanceOf( NameRefNode.class ) ) );
assertThat( in.getLeft().getText(), is( "foo" ) );
assertThat( in.getRight(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( in.getRight().getText(), is( "bar * 10" ) );
}
@Test
public void testConditionalLogicalOp() {
String inputExpression = "foo < 10 and bar = \"x\" or baz";
BaseNode infix = parse( inputExpression );
assertThat( infix, is( instanceOf( InfixOpNode.class ) ) );
assertThat( infix.getText(), is( inputExpression ) );
InfixOpNode or = (InfixOpNode) infix;
assertThat( or.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( or.getLeft().getText(), is( "foo < 10 and bar = \"x\"" ) );
assertThat( or.getOperator(), is( InfixOpNode.InfixOperator.OR ) );
assertThat( or.getRight(), is( instanceOf( NameRefNode.class ) ) );
assertThat( or.getRight().getText(), is( "baz" ) );
InfixOpNode and = (InfixOpNode) or.getLeft();
assertThat( and.getLeft(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( and.getLeft().getText(), is( "foo < 10" ) );
assertThat( and.getOperator(), is( InfixOpNode.InfixOperator.AND ) );
assertThat( and.getRight(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( and.getRight().getText(), is( "bar = \"x\"" ) );
}
@Test
public void testEmptyList() {
String inputExpression = "[]";
BaseNode list = parse( inputExpression );
assertThat( list, is( instanceOf( ListNode.class ) ) );
assertThat( list.getText(), is( inputExpression ) );
ListNode ln = (ListNode) list;
assertThat( ln.getElements(), is( empty() ));
}
@Test
public void testExpressionList() {
String inputExpression = "[ 10, foo * bar, true ]";
BaseNode list = parse( inputExpression );
assertThat( list, is( instanceOf( ListNode.class ) ) );
assertThat( list.getText(), is( "10, foo * bar, true" ) );
ListNode ln = (ListNode) list;
assertThat( ln.getElements().size(), is( 3 ) );
assertThat( ln.getElements().get( 0 ), is( instanceOf( NumberNode.class ) ) );
assertThat( ln.getElements().get( 1 ), is( instanceOf( InfixOpNode.class ) ) );
assertThat( ln.getElements().get( 2 ), is( instanceOf( BooleanNode.class ) ) );
}
@Test
public void testEmptyContext() {
String inputExpression = "{}";
BaseNode list = parse( inputExpression );
assertThat( list, is( instanceOf( ContextNode.class ) ) );
assertThat( list.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) list;
assertThat( ctx.getEntries(), is( empty() ));
}
@Test
public void testContextWithMultipleEntries() {
String inputExpression = "{ \"a string key\" : 10,"
+ " a non-string key : foo+bar,"
+ " a key.with + /' odd chars : [10..50] }";
BaseNode ctxbase = parse( inputExpression );
assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) );
assertThat( ctxbase.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) ctxbase;
assertThat( ctx.getEntries().size(), is( 3 ) );
ContextEntryNode entry = ctx.getEntries().get( 0 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
NameDefNode name = (NameDefNode) entry.getName();
assertThat( name.getName(), is( notNullValue() ) );
assertThat( name.getName(), is("\"a string key\"") );
assertThat( entry.getValue(), is( instanceOf( NumberNode.class ) ) );
assertThat( entry.getValue().getText(), is("10") );
entry = ctx.getEntries().get( 1 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
name = (NameDefNode) entry.getName();
assertThat( name.getParts(), is( notNullValue() ) );
assertThat( name.getParts().size(), is( 5 ) );
assertThat( entry.getName().getText(), is("a non-string key") );
assertThat( entry.getValue(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( entry.getValue().getText(), is( "foo+bar" ) );
entry = ctx.getEntries().get( 2 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
name = (NameDefNode) entry.getName();
assertThat( name.getParts(), is( notNullValue() ) );
assertThat( name.getParts().size(), is( 9 ) );
assertThat( entry.getName().getText(), is("a key.with + /' odd chars") );
assertThat( entry.getValue(), is( instanceOf( RangeNode.class ) ) );
assertThat( entry.getValue().getText(), is( "[10..50]" ) );
}
@Test
public void testNestedContexts() {
String inputExpression = "{ a value : 10,"
+ " an applicant : { "
+ " first name : \"Edson\", "
+ " last + name : \"Tirelli\", "
+ " full name : first name + last + name, "
+ " address : {"
+ " street : \"55 broadway st\","
+ " city : \"New York\" "
+ " }, "
+ " xxx: last + name"
+ " } "
+ "}";
BaseNode ctxbase = parse( inputExpression );
assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) );
assertThat( ctxbase.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) ctxbase;
assertThat( ctx.getEntries().size(), is( 2 ) );
ContextEntryNode entry = ctx.getEntries().get( 0 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
NameDefNode name = (NameDefNode) entry.getName();
assertThat( name.getText(), is("a value") );
assertThat( entry.getValue(), is( instanceOf( NumberNode.class ) ) );
assertThat( entry.getValue().getText(), is("10") );
entry = ctx.getEntries().get( 1 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
name = (NameDefNode) entry.getName();
assertThat( name.getText(), is( "an applicant" ) );
assertThat( entry.getValue(), is( instanceOf( ContextNode.class ) ) );
ContextNode applicant = (ContextNode) entry.getValue();
assertThat( applicant.getEntries().size(), is( 5 ) );
assertThat( applicant.getEntries().get( 0 ).getName().getText(), is("first name") );
assertThat( applicant.getEntries().get( 1 ).getName().getText(), is("last + name") );
assertThat( applicant.getEntries().get( 2 ).getName().getText(), is("full name") );
assertThat( applicant.getEntries().get( 3 ).getName().getText(), is("address") );
assertThat( applicant.getEntries().get( 3 ).getValue(), is( instanceOf( ContextNode.class ) ) );
ContextNode address = (ContextNode) applicant.getEntries().get( 3 ).getValue();
assertThat( address.getEntries().size(), is( 2 ) );
assertThat( address.getEntries().get( 0 ).getName().getText(), is("street") );
assertThat( address.getEntries().get( 1 ).getName().getText(), is("city") );
}
@Test
public void testNestedContexts2() {
String inputExpression = "{ an applicant : { "
+ " home address : {"
+ " street name: \"broadway st\","
+ " city : \"New York\" "
+ " } "
+ " },\n "
+ " street : an applicant.home address.street name \n"
+ "}";
BaseNode ctxbase = parse( inputExpression );
assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) );
assertThat( ctxbase.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) ctxbase;
assertThat( ctx.getEntries().size(), is( 2 ) );
ContextEntryNode entry = ctx.getEntries().get( 1 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
NameDefNode name = (NameDefNode) entry.getName();
assertThat( name.getText(), is("street") );
assertThat( entry.getValue(), is( instanceOf( QualifiedNameNode.class ) ) );
QualifiedNameNode qnn = (QualifiedNameNode) entry.getValue();
assertThat( qnn.getParts().get( 0 ).getText(), is("an applicant") );
assertThat( qnn.getParts().get( 1 ).getText(), is("home address") );
assertThat( qnn.getParts().get( 2 ).getText(), is("street name") );
}
@Test
public void testFunctionDefinition() {
String inputExpression = "{ is minor : function( person's age ) person's age < 21 }";
BaseNode ctxbase = parse( inputExpression );
assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) );
assertThat( ctxbase.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) ctxbase;
assertThat( ctx.getEntries().size(), is( 1 ) );
ContextEntryNode entry = ctx.getEntries().get( 0 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
NameDefNode name = (NameDefNode) entry.getName();
assertThat( name.getText(), is("is minor") );
assertThat( entry.getValue(), is( instanceOf( FunctionDefNode.class ) ) );
assertThat( entry.getValue().getText(), is("function( person's age ) person's age < 21") );
FunctionDefNode isMinorFunc = (FunctionDefNode) entry.getValue();
assertThat( isMinorFunc.getFormalParameters().size(), is( 1 ) );
assertThat( isMinorFunc.getFormalParameters().get( 0 ).getText(), is( "person's age" ) );
assertThat( isMinorFunc.isExternal(), is( false ) );
assertThat( isMinorFunc.getBody(), is( instanceOf( InfixOpNode.class ) ) );
}
@Test
public void testExternalFunctionDefinition() {
String inputExpression = "{ trigonometric cosine : function( angle ) external {"
+ " java : {"
+ " class : \"java.lang.Math\","
+ " method signature : \"cos(double)\""
+ " }"
+ "}}";
BaseNode ctxbase = parse( inputExpression );
assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) );
assertThat( ctxbase.getText(), is( inputExpression ) );
ContextNode ctx = (ContextNode) ctxbase;
assertThat( ctx.getEntries().size(), is( 1 ) );
ContextEntryNode entry = ctx.getEntries().get( 0 );
assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) );
NameDefNode name = (NameDefNode) entry.getName();
assertThat( name.getText(), is("trigonometric cosine") );
assertThat( entry.getValue(), is( instanceOf( FunctionDefNode.class ) ) );
assertThat( entry.getValue().getText(), is("function( angle ) external {"
+ " java : {"
+ " class : \"java.lang.Math\","
+ " method signature : \"cos(double)\""
+ " }"
+ "}" ) );
FunctionDefNode cos = (FunctionDefNode) entry.getValue();
assertThat( cos.getFormalParameters().size(), is( 1 ) );
assertThat( cos.getFormalParameters().get( 0 ).getText(), is( "angle" ) );
assertThat( cos.isExternal(), is( true ) );
assertThat( cos.getBody(), is( instanceOf( ContextNode.class ) ) );
ContextNode body = (ContextNode) cos.getBody();
assertThat( body.getEntries().size(), is( 1 ) );
ContextEntryNode java = body.getEntries().get( 0 );
assertThat( java.getName().getText(), is( "java" ) );
assertThat( java.getValue(), is( instanceOf( ContextNode.class ) ) );
ContextNode def = (ContextNode) java.getValue();
assertThat( def.getEntries().size(), is( 2 ) );
assertThat( def.getEntries().get( 0 ).getName().getText(), is( "class" ) );
assertThat( def.getEntries().get( 0 ).getValue(), is( instanceOf( StringNode.class ) ) );
assertThat( def.getEntries().get( 0 ).getValue().getText(), is( "\"java.lang.Math\"" ) );
assertThat( def.getEntries().get( 1 ).getName().getText(), is( "method signature" ) );
assertThat( def.getEntries().get( 1 ).getValue(), is( instanceOf( StringNode.class ) ) );
assertThat( def.getEntries().get( 1 ).getValue().getText(), is( "\"cos(double)\"" ) );
}
@Test
public void testForExpression() {
String inputExpression = "for item in order.items return item.price * item.quantity";
BaseNode forbase = parse( inputExpression );
assertThat( forbase, is( instanceOf( ForExpressionNode.class ) ) );
assertThat( forbase.getText(), is( inputExpression ) );
ForExpressionNode forExpr = (ForExpressionNode) forbase;
assertThat( forExpr.getIterationContexts().size(), is( 1 ) );
assertThat( forExpr.getExpression(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( forExpr.getExpression().getText(), is( "item.price * item.quantity" ) );
IterationContextNode ic = forExpr.getIterationContexts().get( 0 );
assertThat( ic.getName().getText(), is("item") );
assertThat( ic.getExpression(), is( instanceOf( QualifiedNameNode.class ) ) );
assertThat( ic.getExpression().getText(), is("order.items") );
}
@Test
public void testIfExpression() {
String inputExpression = "if applicant.age < 18 then \"declined\" else \"accepted\"";
BaseNode ifBase = parse( inputExpression );
assertThat( ifBase, is( instanceOf( IfExpressionNode.class ) ) );
assertThat( ifBase.getText(), is( inputExpression ) );
IfExpressionNode ifExpr = (IfExpressionNode) ifBase;
assertThat( ifExpr.getCondition().getText(), is( "applicant.age < 18" ) );
assertThat( ifExpr.getThenExpression().getText(), is( "\"declined\"" ) );
assertThat( ifExpr.getElseExpression().getText(), is( "\"accepted\"" ) );
}
@Test
public void testQuantifiedExpressionSome() {
String inputExpression = "some item in order.items satisfies item.price > 100";
BaseNode someBase = parse( inputExpression );
assertThat( someBase, is( instanceOf( QuantifiedExpressionNode.class ) ) );
assertThat( someBase.getText(), is( inputExpression ) );
QuantifiedExpressionNode someExpr = (QuantifiedExpressionNode) someBase;
assertThat( someExpr.getQuantifier(), is( QuantifiedExpressionNode.Quantifier.SOME ) );
assertThat( someExpr.getIterationContexts().size(), is( 1 ) );
assertThat( someExpr.getIterationContexts().get( 0 ).getText(), is( "item in order.items" ) );
assertThat( someExpr.getExpression().getText(), is( "item.price > 100" ) );
}
@Test
public void testQuantifiedExpressionEvery() {
String inputExpression = "every item in order.items satisfies item.price > 100";
BaseNode someBase = parse( inputExpression );
assertThat( someBase, is( instanceOf( QuantifiedExpressionNode.class ) ) );
assertThat( someBase.getText(), is( inputExpression ) );
QuantifiedExpressionNode someExpr = (QuantifiedExpressionNode) someBase;
assertThat( someExpr.getQuantifier(), is( QuantifiedExpressionNode.Quantifier.EVERY ) );
assertThat( someExpr.getIterationContexts().size(), is( 1 ) );
assertThat( someExpr.getIterationContexts().get( 0 ).getText(), is( "item in order.items" ) );
assertThat( someExpr.getExpression().getText(), is( "item.price > 100" ) );
}
@Test
public void testInstanceOfExpression() {
String inputExpression = "\"foo\" instance of string";
BaseNode instanceOfBase = parse( inputExpression );
assertThat( instanceOfBase, is( instanceOf( InstanceOfNode.class ) ) );
assertThat( instanceOfBase.getText(), is( inputExpression ) );
InstanceOfNode ioExpr = (InstanceOfNode) instanceOfBase;
assertThat( ioExpr.getExpression(), is( instanceOf( StringNode.class ) ) );
assertThat( ioExpr.getExpression().getText(), is( "\"foo\"" ) );
assertThat( ioExpr.getType(), is( instanceOf( TypeNode.class ) ) );
assertThat( ioExpr.getType().getText(), is( "string" ) );
}
@Test
public void testInstanceOfExpressionAnd() {
String inputExpression = "\"foo\" instance of string and 10 instance of number";
BaseNode andExpr = parse( inputExpression );
assertThat( andExpr, is( instanceOf( InfixOpNode.class ) ) );
assertThat( andExpr.getText(), is( inputExpression ) );
InfixOpNode and = (InfixOpNode) andExpr;
assertThat( and.getOperator(), is( InfixOpNode.InfixOperator.AND ) );
assertThat( and.getLeft(), is( instanceOf( InstanceOfNode.class ) ) );
assertThat( and.getRight(), is( instanceOf( InstanceOfNode.class ) ) );
assertThat( and.getLeft().getText(), is( "\"foo\" instance of string" ) );
assertThat( and.getRight().getText(), is( "10 instance of number" ) );
InstanceOfNode ioExpr = (InstanceOfNode) and.getLeft();
assertThat( ioExpr.getExpression(), is( instanceOf( StringNode.class ) ) );
assertThat( ioExpr.getExpression().getText(), is( "\"foo\"" ) );
assertThat( ioExpr.getType(), is( instanceOf( TypeNode.class ) ) );
assertThat( ioExpr.getType().getText(), is( "string" ) );
ioExpr = (InstanceOfNode) and.getRight();
assertThat( ioExpr.getExpression(), is( instanceOf( NumberNode.class ) ) );
assertThat( ioExpr.getExpression().getText(), is( "10" ) );
assertThat( ioExpr.getType(), is( instanceOf( TypeNode.class ) ) );
assertThat( ioExpr.getType().getText(), is( "number" ) );
}
@Test
public void testInstanceOfExpressionFunction() {
String inputExpression = "duration instance of function";
BaseNode instanceOfBase = parse( inputExpression );
assertThat( instanceOfBase, is( instanceOf( InstanceOfNode.class ) ) );
assertThat( instanceOfBase.getText(), is( inputExpression ) );
InstanceOfNode ioExpr = (InstanceOfNode) instanceOfBase;
assertThat( ioExpr.getExpression(), is( instanceOf( NameRefNode.class ) ) );
assertThat( ioExpr.getExpression().getText(), is( "duration" ) );
assertThat( ioExpr.getType(), is( instanceOf( TypeNode.class ) ) );
assertThat( ioExpr.getType().getText(), is( "function" ) );
}
@Test
public void testPathExpression() {
String inputExpression = "[ 10, 15 ].size";
BaseNode pathBase = parse( inputExpression );
assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) );
assertThat( pathBase.getText(), is( inputExpression ) );
PathExpressionNode pathExpr = (PathExpressionNode) pathBase;
assertThat( pathExpr.getExpression(), is( instanceOf( ListNode.class ) ) );
assertThat( pathExpr.getExpression().getText(), is( "10, 15" ) );
assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( pathExpr.getName().getText(), is( "size" ) );
}
@Test
public void testFilterExpression() {
String inputExpression = "[ {x:1, y:2}, {x:2, y:3} ][ x=1 ]";
BaseNode filterBase = parse( inputExpression );
assertThat( filterBase, is( instanceOf( FilterExpressionNode.class ) ) );
assertThat( filterBase.getText(), is( inputExpression ) );
FilterExpressionNode filter = (FilterExpressionNode) filterBase;
assertThat( filter.getExpression(), is( instanceOf( ListNode.class ) ) );
assertThat( filter.getExpression().getText(), is( "{x:1, y:2}, {x:2, y:3}" ) );
assertThat( filter.getFilter(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( filter.getFilter().getText(), is( "x=1" ) );
}
@Test
public void testFunctionInvocationNamedParams() {
String inputExpression = "my.test.Function( named parameter 1 : x+10, named parameter 2 : \"foo\" )";
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( QualifiedNameNode.class ) ) );
assertThat( function.getName().getText(), is( "my.test.Function" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements().size(), is( 2 ) );
assertThat( function.getParams().getElements().get( 0 ), is( instanceOf( NamedParameterNode.class ) ) );
assertThat( function.getParams().getElements().get( 1 ), is( instanceOf( NamedParameterNode.class ) ) );
NamedParameterNode named = (NamedParameterNode) function.getParams().getElements().get( 0 );
assertThat( named.getText(), is( "named parameter 1 : x+10" ) );
assertThat( named.getName().getText(), is( "named parameter 1" ) );
assertThat( named.getExpression(), is( instanceOf( InfixOpNode.class ) ) );
assertThat( named.getExpression().getText(), is( "x+10" ) );
named = (NamedParameterNode) function.getParams().getElements().get( 1 );
assertThat( named.getText(), is( "named parameter 2 : \"foo\"" ) );
assertThat( named.getName().getText(), is( "named parameter 2" ) );
assertThat( named.getExpression(), is( instanceOf( StringNode.class ) ) );
assertThat( named.getExpression().getText(), is( "\"foo\"" ) );
}
@Test
public void testFunctionInvocationPositionalParams() {
String inputExpression = "my.test.Function( x+10, \"foo\" )";
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( QualifiedNameNode.class ) ) );
assertThat( function.getName().getText(), is( "my.test.Function" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements().size(), is( 2 ) );
assertThat( function.getParams().getElements().get( 0 ), is( instanceOf( InfixOpNode.class ) ) );
assertThat( function.getParams().getElements().get( 1 ), is( instanceOf( StringNode.class ) ) );
}
@Test
public void testFunctionInvocationWithKeyword() {
String inputExpression = "date and time( \"2016-07-29T19:47:53\" )";
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( function.getName().getText(), is( "date and time" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements().size(), is( 1 ) );
assertThat( function.getParams().getElements().get( 0 ), is( instanceOf( StringNode.class ) ) );
}
@Test
public void testFunctionInvocationWithExpressionParameters() {
String inputExpression = "date and time( date(\"2016-07-29\"), time(\"19:47:53\") )";
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( function.getName().getText(), is( "date and time" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements().size(), is( 2 ) );
assertThat( function.getParams().getElements().get( 0 ), is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( function.getParams().getElements().get( 1 ), is( instanceOf( FunctionInvocationNode.class ) ) );
}
@Test
public void testFunctionInvocationEmptyParams() {
String inputExpression = "my.test.Function()";
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( QualifiedNameNode.class ) ) );
assertThat( function.getName().getText(), is( "my.test.Function" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements(), is( empty() ) );
}
@Test
public void testFunctionDecisionTableInvocation() {
String inputExpression = "decision table( "
+ " outputs: \"Applicant Risk Rating\","
+ " input expression list: [\"Applicant Age\", \"Medical History\"],"
+ " rule list: ["
+ " [ >60 , \"good\" , \"Medium\" ],"
+ " [ >60 , \"bad\" , \"High\" ],"
+ " [ [25..60] , - , \"Medium\" ],"
+ " [ <25 , \"good\" , \"Low\" ],"
+ " [ <25 , \"bad\" , \"Medium\" ] ],"
+ " hit policy: \"Unique\" )";
// need to call parse passing in the input variables
BaseNode functionBase = parse( inputExpression );
assertThat( functionBase, is( instanceOf( FunctionInvocationNode.class ) ) );
assertThat( functionBase.getText(), is( inputExpression ) );
FunctionInvocationNode function = (FunctionInvocationNode) functionBase;
assertThat( function.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( function.getName().getText(), is( "decision table" ) );
assertThat( function.getParams(), is( instanceOf( ListNode.class ) ) );
assertThat( function.getParams().getElements().size(), is( 4 ) );
assertThat( function.getParams().getElements().get( 0 ), is( instanceOf( NamedParameterNode.class ) ) );
assertThat( function.getParams().getElements().get( 1 ), is( instanceOf( NamedParameterNode.class ) ) );
assertThat( function.getParams().getElements().get( 2 ), is( instanceOf( NamedParameterNode.class ) ) );
assertThat( function.getParams().getElements().get( 3 ), is( instanceOf( NamedParameterNode.class ) ) );
NamedParameterNode named = (NamedParameterNode) function.getParams().getElements().get( 0 );
assertThat( named.getText(), is( "outputs: \"Applicant Risk Rating\"" ) );
assertThat( named.getName().getText(), is( "outputs" ) );
assertThat( named.getExpression(), is( instanceOf( StringNode.class ) ) );
assertThat( named.getExpression().getText(), is( "\"Applicant Risk Rating\"" ) );
named = (NamedParameterNode) function.getParams().getElements().get( 1 );
assertThat( named.getName().getText(), is( "input expression list" ) );
assertThat( named.getExpression(), is( instanceOf( ListNode.class ) ) );
ListNode list = (ListNode) named.getExpression();
assertThat( list.getElements().size(), is( 2 ) );
assertThat( list.getElements().get( 0 ), is( instanceOf( StringNode.class ) ) );
assertThat( list.getElements().get( 0 ).getText(), is( "\"Applicant Age\"" ) );
assertThat( list.getElements().get( 1 ), is( instanceOf( StringNode.class ) ) );
assertThat( list.getElements().get( 1 ).getText(), is( "\"Medical History\"" ) );
named = (NamedParameterNode) function.getParams().getElements().get( 2 );
assertThat( named.getName().getText(), is( "rule list" ) );
assertThat( named.getExpression(), is( instanceOf( ListNode.class ) ) );
list = (ListNode) named.getExpression();
assertThat( list.getElements().size(), is( 5 ) );
assertThat( list.getElements().get( 0 ), is( instanceOf( ListNode.class ) ) );
ListNode rule = (ListNode) list.getElements().get( 0 );
assertThat( rule.getElements().size(), is( 3 ) );
assertThat( rule.getElements().get( 0 ), is( instanceOf( UnaryTestNode.class ) ) );
assertThat( rule.getElements().get( 0 ).getText(), is( ">60" ) );
assertThat( rule.getElements().get( 1 ), is( instanceOf( StringNode.class ) ) );
assertThat( rule.getElements().get( 1 ).getText(), is( "\"good\"" ) );
assertThat( rule.getElements().get( 2 ), is( instanceOf( StringNode.class ) ) );
assertThat( rule.getElements().get( 2 ).getText(), is( "\"Medium\"" ) );
named = (NamedParameterNode) function.getParams().getElements().get( 3 );
assertThat( named.getName().getText(), is( "hit policy" ) );
assertThat( named.getExpression(), is( instanceOf( StringNode.class ) ) );
assertThat( named.getExpression().getText(), is( "\"Unique\"" ) );
}
@Test
public void testContextPathExpression() {
String inputExpression = "{ x : \"foo\" }.x";
BaseNode pathBase = parse( inputExpression );
assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) );
assertThat( pathBase.getText(), is( inputExpression ) );
PathExpressionNode pathExpr = (PathExpressionNode) pathBase;
assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) );
assertThat( pathExpr.getExpression().getText(), is( "{ x : \"foo\" }" ) );
assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( pathExpr.getName().getText(), is( "x" ) );
}
@Test
public void testContextPathExpression2() {
String inputExpression = "{ x : { y : \"foo\" } }.x.y";
BaseNode pathBase = parse( inputExpression );
assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) );
assertThat( pathBase.getText(), is( inputExpression ) );
PathExpressionNode pathExpr = (PathExpressionNode) pathBase;
assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) );
assertThat( pathExpr.getExpression().getText(), is( "{ x : { y : \"foo\" } }" ) );
assertThat( pathExpr.getName(), is( instanceOf( QualifiedNameNode.class ) ) );
assertThat( pathExpr.getName().getText(), is( "x.y" ) );
}
@Test
public void testContextPathExpression3() {
String inputExpression = "{ first name : \"bob\" }.first name";
BaseNode pathBase = parse( inputExpression );
assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) );
assertThat( pathBase.getText(), is( inputExpression ) );
PathExpressionNode pathExpr = (PathExpressionNode) pathBase;
assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) );
assertThat( pathExpr.getExpression().getText(), is( "{ first name : \"bob\" }" ) );
assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) );
assertThat( pathExpr.getName().getText(), is( "first name" ) );
}
@Test
public void testVariableName() {
String var = "valid variable name";
assertThat( FEELParser.isVariableNameValid( var ), is( true ) );
}
@Test
public void testVariableNameWithValidCharacters() {
String var = "?_873./-'+*valid";
assertThat( FEELParser.isVariableNameValid( var ), is( true ) );
}
@Test
public void testVariableNameWithInvalidCharacterPercent() {
String var = "?_873./-'%+*valid";
assertThat( FEELParser.isVariableNameValid( var ), is( false ) );
assertThat( FEELParser.checkVariableName( var ).get( 0 ).getMessage(), is( Msg.createMessage(Msg.INVALID_VARIABLE_NAME, "character", "%") ) );
}
@Test
public void testVariableNameInvalidStartCharacter() {
String var = "5variable can't start with a number";
assertThat( FEELParser.isVariableNameValid( var ), is( false ) );
assertThat( FEELParser.checkVariableName( var ).get( 0 ).getMessage(), is( Msg.createMessage(Msg.INVALID_VARIABLE_NAME_START, "character", "5") ) );
}
@Test
public void testVariableNameCantContainKeywordIn() {
String var = "variable can't contain 'in' keyword";
assertThat( FEELParser.isVariableNameValid( var ), is( false ) );
assertThat( FEELParser.checkVariableName( var ).get( 0 ).getMessage(), is( Msg.createMessage(Msg.INVALID_VARIABLE_NAME, "keyword", "in") ) );
}
@Test
public void testVariableNameCantStartWithKeyword() {
String var = "for keyword is an invalid start for a variable name";
assertThat( FEELParser.isVariableNameValid( var ), is( false ) );
assertThat( FEELParser.checkVariableName( var ).get( 0 ).getMessage(), is( Msg.createMessage(Msg.INVALID_VARIABLE_NAME_START, "keyword", "for") ) );
}
private void assertLocation(String inputExpression, BaseNode number) {
assertThat( number.getText(), is( inputExpression ) );
assertThat( number.getStartChar(), is( 0 ) );
assertThat( number.getStartLine(), is( 1 ) );
assertThat( number.getStartColumn(), is( 0 ) );
assertThat( number.getEndChar(), is( inputExpression.length() - 1 ) );
assertThat( number.getEndLine(), is( 1 ) );
assertThat( number.getEndColumn(), is( inputExpression.length() ) );
}
private BaseNode parse(String input) {
return parse( input, Collections.emptyMap() );
}
private BaseNode parse(String input, Map<String, Object> inputVariables) {
FEEL_1_1Parser parser = FEELParser.parse( null, input, Collections.EMPTY_MAP, inputVariables );
ParseTree tree = parser.expression();
ASTBuilderVisitor v = new ASTBuilderVisitor();
BaseNode expr = v.visit( tree );
return expr;
}
}