summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2017-08-18 16:02:03 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2017-08-18 16:02:03 +0200
commit4a1b03550527cb54d58266b4cfacce53744cac43 (patch)
treea313bc79f8ff5c2a6e2f51dc47d1cbcd56277eaf /searchlib
parentfd70bbb89474220e0556e27a9a8f1ed6edd9bbf6 (diff)
Distinguish the random feature and tensor function
Look ahead far enough to choose correctly between the tensor function 'random(tensor-type)' and the scalar feature 'tensor(literal'"random" feature. This also relaxes Context to allow arguments (to allow testing).
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Context.java31
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java4
-rwxr-xr-xsearchlib/src/main/javacc/RankingExpressionParser.jj2
-rw-r--r--searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java4
-rw-r--r--searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTester.java3
5 files changed, 23 insertions, 21 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Context.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Context.java
index c1720996e9d..785ed78492e 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Context.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Context.java
@@ -2,12 +2,14 @@
package com.yahoo.searchlib.rankingexpression.evaluation;
import com.yahoo.searchlib.rankingexpression.rule.Arguments;
+import com.yahoo.searchlib.rankingexpression.rule.ExpressionNode;
import com.yahoo.tensor.evaluation.EvaluationContext;
import java.util.Set;
+import java.util.stream.Collectors;
/**
- * <p>The context providing value bindings for an expression evaluation.</p>
+ * The context providing value bindings for an expression evaluation.
*
* @author bratseth
*/
@@ -26,14 +28,12 @@ public abstract class Context implements EvaluationContext {
* <code>name(argument*)(.output)?</code>, where <i>argument</i> is any
* string. This may be used to implement more advanced variables whose
* values are calculated at runtime from arguments. Supporting this in a
- * context is optional. Implementations may choose to throw
- * UnsupportedOperationException or always return null, or to handle outputs
- * but not arguments.</p>
- *
- * <p>This default implementation does the latter - if arguments is non-null
- * and non-empty an UnsupportedOperationException is thrown, otherwise
- * get(name + "." + output) is called (or just get(name)) if output is also
- * null.</p>
+ * context is optional.
+ *
+ * <p>This default implementation generates a name on the form
+ * <code>name(argument1, argument2, ...argumentN).output</code>.
+ * If there are no arguments the parenthesis are omitted.
+ * If there is no output, the dot is omitted.</p>
*
* @param name The name of this variable.
* @param arguments The parsed arguments as given in the textual expression.
@@ -41,13 +41,12 @@ public abstract class Context implements EvaluationContext {
* calculation to output several), or null to output the
* "main" (or only) value.
*/
- public Value get(String name, Arguments arguments,String output) {
- if (arguments!=null && arguments.expressions().size() > 0)
- throw new UnsupportedOperationException(this + " does not support structured ranking expression variables, attempted to reference '" +
- name + arguments + "'");
- if (output==null)
- return get(name);
- return get(name + "." + output);
+ public Value get(String name, Arguments arguments, String output) {
+ if (arguments != null && arguments.expressions().size() > 0)
+ name = name + "(" + arguments.expressions().stream().map(ExpressionNode::toString).collect(Collectors.joining(",")) + ")";
+ if (output !=null)
+ name = name + "." + output;
+ return get(name);
}
/**
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
index e5e2ebcb5d2..09895a0c2f6 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
@@ -46,8 +46,8 @@ public class MapContext extends Context {
*/
@Override
public Value get(String key) {
- Value value=bindings.get(key);
- if (value==null) return DoubleValue.zero;
+ Value value = bindings.get(key);
+ if (value == null) return DoubleValue.zero;
return value;
}
diff --git a/searchlib/src/main/javacc/RankingExpressionParser.jj b/searchlib/src/main/javacc/RankingExpressionParser.jj
index 3c62082e147..c3b9235cc93 100755
--- a/searchlib/src/main/javacc/RankingExpressionParser.jj
+++ b/searchlib/src/main/javacc/RankingExpressionParser.jj
@@ -227,7 +227,7 @@ ExpressionNode value() :
( [ LOOKAHEAD(2) <SUB> { neg = true; } ]
( ret = constantPrimitive() |
LOOKAHEAD(2) ret = ifExpression() |
- LOOKAHEAD(2) ret = function() |
+ LOOKAHEAD(4) ret = function() |
ret = feature() |
ret = queryFeature() |
( <LBRACE> ret = expression() <RBRACE> { ret = new EmbracedNode(ret); } ) ) )
diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java
index fea272216c6..5d357777657 100644
--- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java
+++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java
@@ -79,6 +79,10 @@ public class EvaluationTestCase {
tester.assertEvaluates(0, "sin(0)");
tester.assertEvaluates(1, "cos(0)");
tester.assertEvaluates(8, "pow(4/2,min(cos(0)*3,5))");
+
+ // Random feature (which is also a tensor function) (We expect to be able to parse it and look up a zero)
+ tester.assertEvaluates(0, "random(1)");
+ tester.assertEvaluates(0, "random(foo)");
// Combined
tester.assertEvaluates(1.25, "5*if(1>=1.1, one_half, if(min(1,2)<max(1,2),if (\"foo\" in [\"foo\",\"bar\"],a_quarter,3000), 0.57345347))");
diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTester.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTester.java
index 47ef69b914a..d67c9dfd9dc 100644
--- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTester.java
+++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTester.java
@@ -16,11 +16,10 @@ import static org.junit.Assert.assertEquals;
*/
public class EvaluationTester {
- private double tolerance = 0.000001;
private MapContext defaultContext;
public EvaluationTester() {
- Map<String, Value> bindings = new HashMap<String, Value>();
+ Map<String, Value> bindings = new HashMap<>();
bindings.put("zero", DoubleValue.frozen(0d));
bindings.put("one", DoubleValue.frozen(1d));
bindings.put("one_half", DoubleValue.frozen(0.5d));