diff --git a/pom.xml b/pom.xml
index 1a52342..411da5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
xyz.cliserkad
smp
jar
- 0.0.19
+ 0.0.20
Simple Data Format
UTF-8
@@ -35,7 +35,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.4.0
+ 3.5.0
true
diff --git a/src/main/antlr4/SimpleLexer.g4 b/src/main/antlr4/SimpleLexer.g4
index ffeca7b..fb5a887 100644
--- a/src/main/antlr4/SimpleLexer.g4
+++ b/src/main/antlr4/SimpleLexer.g4
@@ -38,4 +38,7 @@ fragment LETTER : UPLETTER | DNLETTER;
fragment ALPHANUM : LETTER | DIGIT;
fragment UNDERSCORE : '_';
CHAR_LIT: '\'' . '\'';
-KEYNAME : .+;
+
+// the specification says you can use any character that is not : but this is much more restrictive
+// this might be changed later to be more permissive, but eliminating more characters makes parsing less ambiguous
+KEY_FRAGMENT: ~[-+_:; \n\t\r{}[\],.\\/*'"];
diff --git a/src/main/antlr4/SimpleParser.g4 b/src/main/antlr4/SimpleParser.g4
index 15415a0..1396e5c 100644
--- a/src/main/antlr4/SimpleParser.g4
+++ b/src/main/antlr4/SimpleParser.g4
@@ -14,7 +14,8 @@ decimal: NEGATIVE? DIGIT+ DOT DIGIT+;
value: object | list | bool | integer | decimal | STRING_LIT | CHAR_LIT;
list: BRACE_OPEN (value SEPARATOR)* BRACE_CLOSE;
-pair: KEYNAME (ASSIGN value) PAIR_END;
+key: KEY_FRAGMENT+?;
+pair: key ASSIGN value PAIR_END;
object: BODY_OPEN pair* BODY_CLOSE;
root: object*;
diff --git a/src/test/java/EncodeTest.java b/src/test/java/EncodeTest.java
index 452aba8..40c2c79 100644
--- a/src/test/java/EncodeTest.java
+++ b/src/test/java/EncodeTest.java
@@ -4,6 +4,7 @@
import xyz.cliserkad.smp.Verifier;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static xyz.cliserkad.smp.SimpleEncoder.encode;
public class EncodeTest {
@@ -13,7 +14,7 @@ public class EncodeTest {
@Test
public void testCar() throws IllegalAccessException {
assertEquals(EXPECTED, encode(new Car()));
- assert Verifier.verifyOrPrint(encode(new Car()));
+ assertTrue(Verifier.verifyOrPrint(encode(new Car())));
}
}
diff --git a/src/test/java/MathTest.java b/src/test/java/MathTest.java
new file mode 100644
index 0000000..6f912dc
--- /dev/null
+++ b/src/test/java/MathTest.java
@@ -0,0 +1,65 @@
+package test.java;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static xyz.cliserkad.util.Math.pow;
+
+public class MathTest {
+
+ @Test
+ public void test0RaisedTo0Is1() {
+ assertEquals(1, pow(0, 0));
+ }
+
+ @Test
+ public void test0RaisedTo1Is0() {
+ assertEquals(0, pow(0, 1));
+ }
+
+ @Test
+ public void test1RaisedTo0Is1() {
+ assertEquals(1, pow(1, 0));
+ }
+
+ @Test
+ public void test1RaisedTo1Is1() {
+ assertEquals(1, pow(1, 1));
+ }
+
+ @Test
+ public void test1RaisedTo2Is1() {
+ assertEquals(1, pow(1, 2));
+ }
+
+ @Test
+ public void test2RaisedTo0Is1() {
+ assertEquals(1, pow(2, 0));
+ }
+
+ @Test
+ public void test2RaisedTo1Is2() {
+ assertEquals(2, pow(2, 1));
+ }
+
+ @Test
+ public void test2RaisedTo2Is4() {
+ assertEquals(4, pow(2, 2));
+ }
+
+ @Test
+ public void test2RaisedTo3Is8() {
+ assertEquals(8, pow(2, 3));
+ }
+
+ @Test
+ public void test2RaisedTo4Is16() {
+ assertEquals(16, pow(2, 4));
+ }
+
+ @Test
+ public void testLargeExponentDoesntCauseStackOverflow() {
+ assertEquals(-2659239065858430293L, pow(3, Integer.MAX_VALUE));
+ }
+
+}
diff --git a/src/test/java/RangeIterationTest.java b/src/test/java/RangeIterationTest.java
index 57cfa55..d590fb7 100644
--- a/src/test/java/RangeIterationTest.java
+++ b/src/test/java/RangeIterationTest.java
@@ -15,7 +15,7 @@ public class RangeIterationTest {
@Test
public void testRange() {
Range range = new Range(0, 10);
- StringBuilder sb = new StringBuilder();
+ StringBuilder sb = new StringBuilder(EXPECTED_OUTPUT_1.length());
for(int i : range) {
sb.append(i);
}
diff --git a/src/test/java/TestDuo.java b/src/test/java/TestDuo.java
new file mode 100644
index 0000000..d77472d
--- /dev/null
+++ b/src/test/java/TestDuo.java
@@ -0,0 +1,37 @@
+package test.java;
+
+import org.junit.jupiter.api.Test;
+import xyz.cliserkad.util.Duo;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class TestDuo {
+
+ @Test
+ public void testPrinting() {
+ Duo duo = new Duo<>("Hello", "World");
+ assertEquals(duo.toString(), "{\n a: \"Hello\";\n b: \"World\";\n}");
+ }
+
+ @Test
+ public void testEquality() {
+ Duo duo1 = new Duo<>("Hello", "World");
+ Duo duo2 = new Duo<>("Hello", "World");
+ assertEquals(duo1, duo2);
+ }
+
+ @Test
+ public void testInequality() {
+ Duo duo1 = new Duo<>("Hello", "World");
+ Duo duo2 = new Duo<>("Hello", "World!");
+ assertEquals(duo1.equals(duo2), false);
+ }
+
+ @Test
+ public void testHashing() {
+ Duo duo1 = new Duo<>("Hello", "World");
+ Duo duo2 = new Duo<>("Hello", "World");
+ assertEquals(duo1.hashCode(), duo2.hashCode());
+ }
+
+}
diff --git a/src/test/java/TestSerialVersionUIDGenerator.java b/src/test/java/TestSerialVersionUIDGenerator.java
new file mode 100644
index 0000000..10299f0
--- /dev/null
+++ b/src/test/java/TestSerialVersionUIDGenerator.java
@@ -0,0 +1,60 @@
+package test.java;
+
+import org.junit.jupiter.api.Test;
+import xyz.cliserkad.util.*;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TestSerialVersionUIDGenerator {
+
+ @Test
+ public void testUIDsAreUnique() {
+ BestList> classesToTest = new BestList<>();
+
+ classesToTest.add(BaseConverter.class);
+ classesToTest.add(BestList.class);
+ classesToTest.add(CheckedFunction.class);
+ classesToTest.add(Copier.class);
+ classesToTest.add(DiskLoc.class);
+ classesToTest.add(Duo.class);
+ classesToTest.add(ElapseTimer.class);
+ classesToTest.add(ExceptionPack.class);
+ classesToTest.add(Levenshtein.class);
+ classesToTest.add(MergeSort.class);
+ classesToTest.add(NamedObject.class);
+ classesToTest.add(NamedObjectList.class);
+ classesToTest.add(Path.class);
+ classesToTest.add(PlaceHolder.class);
+ classesToTest.add(Range.class);
+ classesToTest.add(SerialCopier.class);
+ classesToTest.add(SerialVersionUIDGenerator.class);
+ classesToTest.add(Sizes.class);
+ classesToTest.add(StringList.class);
+ classesToTest.add(Text.class);
+ classesToTest.add(TrackedMap.class);
+ classesToTest.add(Trio.class);
+ classesToTest.add(Tuple.class);
+ classesToTest.add(TupleBase.class);
+ classesToTest.add(UnimplementedException.class);
+ classesToTest.add(Union.class);
+ classesToTest.add(Union2.class);
+ classesToTest.add(Union2Extendable.class);
+ classesToTest.add(Union3.class);
+ classesToTest.add(Union3Extendable.class);
+ classesToTest.add(UnionMember.class);
+ classesToTest.add(Vector2i.class);
+ classesToTest.add(Zipper.class);
+
+ Set serialUIDs = new HashSet<>();
+ for(Class> clazz : classesToTest) {
+ long serialUID = SerialVersionUIDGenerator.generateSerialVersionUID(clazz);
+ assertTrue(serialUIDs.add(serialUID));
+ }
+ assertEquals(serialUIDs.size(), classesToTest.size());
+ }
+
+}
diff --git a/src/test/java/TestTrio.java b/src/test/java/TestTrio.java
new file mode 100644
index 0000000..ba874c2
--- /dev/null
+++ b/src/test/java/TestTrio.java
@@ -0,0 +1,38 @@
+package test.java;
+
+import org.junit.jupiter.api.Test;
+import xyz.cliserkad.util.Trio;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+public class TestTrio {
+
+ @Test
+ public void testPrinting() {
+ Trio trio = new Trio<>("Hello", "World", "!");
+ assertEquals(trio.toString(), "{\n a: \"Hello\";\n b: \"World\";\n c: \"!\";\n}");
+ }
+
+ @Test
+ public void testEquality() {
+ Trio trio1 = new Trio<>("Hello", "World", "!");
+ Trio trio2 = new Trio<>("Hello", "World", "!");
+ assertEquals(trio1, trio2);
+ }
+
+ @Test
+ public void testInequality() {
+ Trio trio1 = new Trio<>("Hello", "World", "!");
+ Trio trio2 = new Trio<>("Hello", "World", "?");
+ assertFalse(trio1.equals(trio2));
+ }
+
+ @Test
+ public void testHashing() {
+ Trio trio1 = new Trio<>("Hello", "World", "!");
+ Trio trio2 = new Trio<>("Hello", "World", "!");
+ assertEquals(trio1.hashCode(), trio2.hashCode());
+ }
+
+}
diff --git a/src/test/java/TestUnion3.java b/src/test/java/TestUnion3.java
new file mode 100644
index 0000000..24518db
--- /dev/null
+++ b/src/test/java/TestUnion3.java
@@ -0,0 +1,57 @@
+package test.java;
+
+import org.junit.jupiter.api.Test;
+import xyz.cliserkad.util.Union3;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class TestUnion3 {
+
+ public Union3 data;
+
+ public String lambdaMatch() {
+ return data.match((str -> {
+ return str;
+ }), (i -> {
+ return "Integers get multiplied: " + i * 5;
+ }), (dbl -> {
+ return "Doubles get addition: " + (dbl + 3.14);
+ }));
+ }
+
+ public String switchMatch() {
+ return switch(data) {
+ case Union3.A a -> a.getValue();
+ case Union3.B, Integer, ?> b -> "Integers get multiplied: " + b.getValue() * 5;
+ case Union3.C, ?, Double> c -> "Doubles get addition: " + (c.getValue() + 3.14);
+ };
+ }
+
+ @Test
+ public void testWithString() {
+ TestUnion3 example = new TestUnion3();
+ example.data = new Union3.A<>("Hello, World!");
+ assertEquals(example.lambdaMatch(), example.switchMatch());
+ assertEquals(example.lambdaMatch(), "Hello, World!");
+ assertEquals(example.switchMatch(), "Hello, World!");
+ }
+
+ @Test
+ public void testWithInteger() {
+ TestUnion3 example = new TestUnion3();
+ example.data = new Union3.B<>(2);
+ assertEquals(example.lambdaMatch(), example.switchMatch());
+ assertEquals(example.lambdaMatch(), "Integers get multiplied: 10");
+ assertEquals(example.switchMatch(), "Integers get multiplied: 10");
+ }
+
+ @Test
+ public void testWithDouble() {
+ TestUnion3 example = new TestUnion3();
+ example.data = new Union3.C<>(3.14);
+ assertEquals(example.lambdaMatch(), example.switchMatch());
+ assertEquals(example.lambdaMatch(), "Doubles get addition: 6.28");
+ assertEquals(example.switchMatch(), "Doubles get addition: 6.28");
+ }
+
+}
diff --git a/src/xyz/cliserkad/smp/BadTemplateException.java b/src/xyz/cliserkad/smp/BadTemplateException.java
index 07a863b..b0f9445 100644
--- a/src/xyz/cliserkad/smp/BadTemplateException.java
+++ b/src/xyz/cliserkad/smp/BadTemplateException.java
@@ -1,8 +1,13 @@
package xyz.cliserkad.smp;
+import java.io.Serial;
+
+import static xyz.cliserkad.util.SerialVersionUIDGenerator.generateSerialVersionUID;
+
public class BadTemplateException extends Exception {
- private static final long serialVersionUID = -7085178496879726407L;
+ @Serial
+ private static final long serialVersionUID = generateSerialVersionUID(BadTemplateException.class);
private final Class> template;
private final ReflectiveOperationException cause;
diff --git a/src/xyz/cliserkad/smp/ParseData.java b/src/xyz/cliserkad/smp/ParseData.java
index 9ad3cc4..a5bfc1e 100644
--- a/src/xyz/cliserkad/smp/ParseData.java
+++ b/src/xyz/cliserkad/smp/ParseData.java
@@ -2,12 +2,14 @@
import xyz.cliserkad.util.Path;
+import java.io.Serial;
+
+import static xyz.cliserkad.util.SerialVersionUIDGenerator.generateSerialVersionUID;
+
public class ParseData extends PathMap