diff --git a/pom.xml b/pom.xml
index 35df154..339882a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
parsington
- 3.1.1-SNAPSHOT
+ 3.2.0-SNAPSHOT
Parsington: The SciJava Expression Parser
A general-purpose mathematical expression parser, which converts infix expression strings into postfix queues and/or syntax trees.
diff --git a/src/main/java/org/scijava/parsington/eval/AbstractEvaluator.java b/src/main/java/org/scijava/parsington/eval/AbstractEvaluator.java
index f4099ff..9dc4ae9 100644
--- a/src/main/java/org/scijava/parsington/eval/AbstractEvaluator.java
+++ b/src/main/java/org/scijava/parsington/eval/AbstractEvaluator.java
@@ -30,6 +30,7 @@
package org.scijava.parsington.eval;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -79,6 +80,11 @@ public Object get(final String name) {
return new Unresolved(name);
}
+ @Override
+ public Map getAll() {
+ return Collections.unmodifiableMap(vars);
+ }
+
@Override
public void set(final String name, final Object value) {
vars.put(name, value);
@@ -89,4 +95,14 @@ public void setAll(final Map extends String, ? extends Object> map) {
vars.putAll(map);
}
+ @Override
+ public Object remove(final String name) {
+ return vars.remove(name);
+ }
+
+ @Override
+ public void clear() {
+ vars.clear();
+ }
+
}
diff --git a/src/main/java/org/scijava/parsington/eval/Evaluator.java b/src/main/java/org/scijava/parsington/eval/Evaluator.java
index 3ebf1e9..1be84d2 100644
--- a/src/main/java/org/scijava/parsington/eval/Evaluator.java
+++ b/src/main/java/org/scijava/parsington/eval/Evaluator.java
@@ -167,6 +167,13 @@ default Object get(final Variable v) {
return get(v.getToken());
}
+ /**
+ * Gets a map of all variable names and values.
+ *
+ * @return A map from variable names to variable values.
+ */
+ Map getAll();
+
/**
* Sets the value of a variable.
*
@@ -184,4 +191,19 @@ default void set(final Variable v, final Object value) {
*/
void setAll(Map extends String, ? extends Object> map);
+ /**
+ * Removes the named variable.
+ *
+ * @param name The name of the variable whose value you want to remove.
+ * @return The previous variables value associated with name,
+ * or null if the name did not exist.
+ */
+ Object remove(String name);
+
+ /**
+ * Clears all the variables.
+ *
+ */
+ void clear();
+
}
diff --git a/src/test/java/org/scijava/parsington/eval/AbstractEvaluatorTest.java b/src/test/java/org/scijava/parsington/eval/AbstractEvaluatorTest.java
new file mode 100644
index 0000000..62d5fc9
--- /dev/null
+++ b/src/test/java/org/scijava/parsington/eval/AbstractEvaluatorTest.java
@@ -0,0 +1,118 @@
+/*
+ * #%L
+ * Parsington: the SciJava mathematical expression parser.
+ * %%
+ * Copyright (C) 2015 - 2026 Board of Regents of the University of
+ * Wisconsin-Madison.
+ * %%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * #L%
+ */
+
+package org.scijava.parsington.eval;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.scijava.parsington.AbstractTest;
+
+/**
+ * Abstract base class for testing {@link Evaluator} implementations.
+ *
+ * @author Curtis Rueden
+ */
+public abstract class AbstractEvaluatorTest extends AbstractTest {
+
+ public abstract Evaluator createEvaluator();
+
+ /**
+ * Tests {@link Evaluator#get(String)} and
+ * {@link Evaluator#set(String, Object)}.
+ */
+ @Test
+ public void testGetSet() {
+ final Evaluator e = createEvaluator();
+ // In strict mode (the default), getting an unset variable throws.
+ assertThrows(IllegalArgumentException.class, () -> e.get("x"));
+ e.set("x", 42);
+ assertEquals(42, e.get("x"));
+ e.set("x", "hello");
+ assertEquals("hello", e.get("x"));
+ }
+
+ /** Tests {@link Evaluator#remove(String)}. */
+ @Test
+ public void testRemove() {
+ final Evaluator e = createEvaluator();
+ // Removing an absent variable returns null.
+ assertNull(e.remove("x"));
+ e.set("x", 99);
+ assertEquals(99, e.remove("x"));
+ // Variable is gone after removal.
+ assertThrows(IllegalArgumentException.class, () -> e.get("x"));
+ }
+
+ /** Tests {@link Evaluator#clear()}. */
+ @Test
+ public void testClear() {
+ final Evaluator e = createEvaluator();
+ e.set("a", 1);
+ e.set("b", 2);
+ e.clear();
+ assertEquals(new HashMap<>(), e.getAll());
+ assertThrows(IllegalArgumentException.class, () -> e.get("a"));
+ assertThrows(IllegalArgumentException.class, () -> e.get("b"));
+ }
+
+ /** Tests {@link Evaluator#getAll()} and {@link Evaluator#setAll(Map)}. */
+ @Test
+ public void testGetAllSetAll() {
+ final Evaluator e = createEvaluator();
+ assertEquals(new HashMap<>(), e.getAll());
+
+ final Map vars = new HashMap<>();
+ vars.put("a", 1);
+ vars.put("b", "two");
+ vars.put("c", 3.0);
+ e.setAll(vars);
+
+ assertEquals(vars, e.getAll());
+
+ // Verify individual get still works after setAll.
+ assertEquals(1, e.get("a"));
+ assertEquals("two", e.get("b"));
+ assertEquals(3.0, e.get("c"));
+
+ // Verify variables created at evaluation are accessible and correct.
+ e.evaluate("d=a+c");
+ assertTrue(e.getAll().containsKey("d"));
+ final Object dVal = e.get("d");
+ assertEquals(4.0, dVal);
+ assertEquals(dVal, e.getAll().get("d"));
+ }
+}
diff --git a/src/test/java/org/scijava/parsington/eval/AbstractStandardEvaluatorTest.java b/src/test/java/org/scijava/parsington/eval/AbstractStandardEvaluatorTest.java
index f1a2955..7476c8c 100644
--- a/src/test/java/org/scijava/parsington/eval/AbstractStandardEvaluatorTest.java
+++ b/src/test/java/org/scijava/parsington/eval/AbstractStandardEvaluatorTest.java
@@ -45,13 +45,12 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.scijava.parsington.AbstractTest;
import org.scijava.parsington.Operators;
import org.scijava.parsington.SyntaxTree;
import org.scijava.parsington.Variable;
/** Abstract base class for testing {@link StandardEvaluator} implementations. */
-public abstract class AbstractStandardEvaluatorTest extends AbstractTest {
+public abstract class AbstractStandardEvaluatorTest extends AbstractEvaluatorTest {
protected StandardEvaluator e;
@@ -60,6 +59,7 @@ public void setUp() {
e = createEvaluator();
}
+ @Override
public abstract StandardEvaluator createEvaluator();
/** Tests {@link Evaluator#evaluate(String)}. */