Skip to content

Commit

Permalink
Expression MP mode
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez committed Oct 3, 2024
1 parent e6756ee commit 69ff45b
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,11 @@ private static Node parseString(Itr itr, final boolean allowExpr, final boolean
} else if (flags.contains(Flag.NO_$$)) {
list.add(LiteralNode.DOLLAR);
itr.prev();
} else if (flags.contains(Flag.MP)) {
list.add(LiteralNode.DOLLAR);
if (!itr.hasNext() || itr.peekNext() != '{') {
itr.prev();
}
} else {
// just resolve $$ to $
// TP 14
Expand Down Expand Up @@ -556,7 +561,7 @@ private static Node parseString(Itr itr, final boolean allowExpr, final boolean
//throw Assert.unreachableCode();
}
case '\\': {
if (flags.contains(Flag.ESCAPES)) {
if (flags.contains(Flag.ESCAPES) || flags.contains(Flag.MP)) {
if (idx > start) {
list.add(new LiteralNode(itr.getStr(), start, idx));
start = idx;
Expand All @@ -570,7 +575,7 @@ private static Node parseString(Itr itr, final boolean allowExpr, final boolean
// TP 34
throw invalidExpressionSyntax(itr.getStr(), idx);
}
} else {
} else if (flags.contains(Flag.ESCAPES)) {
ch = itr.next();
final LiteralNode node;
switch (ch) {
Expand Down Expand Up @@ -622,6 +627,17 @@ private static Node parseString(Itr itr, final boolean allowExpr, final boolean
list.add(node);
start = itr.getNextIdx();
continue;
} else if (flags.contains(Flag.MP)) {
ch = itr.next();
if (ch == '$') {
if (!itr.hasNext() || itr.peekNext() != '{') {
list.add(LiteralNode.BACKSLASH);
}
} else {
list.add(LiteralNode.BACKSLASH);
}
start = itr.getPrevIdx();
continue;
}
}
// TP 42
Expand Down Expand Up @@ -699,15 +715,19 @@ public enum Flag {
*/
GENERAL_EXPANSION,
/**
* Support standard escape sequences in plain text and default value fields, which begin with a backslash ("{@code \}")
* character.
* Support standard escape sequences in plain text and default value fields, which begin with a backslash
* {@code \} character.
*/
ESCAPES,
/**
* Escaping <code>$</code> with <code>$$</code> or <code>/$</code> only applies when <code>{</code> follows
* the initial escaped <code>$</code>.
* No escape sequence for {@code $} which begin with a dollar {@code $}.
*/
NO_$$,
/**
* Supports escape sequences for expressions {@code ${}}, which begin with a backslash {@code \} or dollar
* {@code $}.
*/
MP,
/**
* Treat expressions containing a double-colon delimiter as special, encoding the entire content into the key.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,8 @@ void expressions() {

@Test
void no$$Escapes() {
assertEquals("$", Expression.compile("\\$", ESCAPES).evaluate((c, b) -> {
}));
assertEquals("$", Expression.compile("\\$", NO_$$, ESCAPES).evaluate((c, b) -> {
}));
assertEquals("${foo}", Expression.compile("\\${foo}", NO_$$, ESCAPES).evaluate((c, b) -> {
Expand All @@ -809,4 +811,119 @@ void expressions() {
assertEquals("bar", c.getKey());
}));
}

@Test
void mp() {
assertThrows(IllegalArgumentException.class, () -> Expression.compile("$", MP).evaluate((c, b) -> {
}));
assertEquals("$", Expression.compile("$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertThrows(IllegalArgumentException.class, () -> Expression.compile("$$", MP).evaluate((c, b) -> {
}));
assertEquals("$$", Expression.compile("$$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertEquals("\\$", Expression.compile("\\$", MP).evaluate((c, b) -> {
}));

assertThrows(IllegalArgumentException.class, () -> Expression.compile("\\$$", MP).evaluate((c, b) -> {
}));
assertEquals("\\$$", Expression.compile("\\$$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertThrows(IllegalArgumentException.class, () -> Expression.compile("$$foo", MP).evaluate((c, b) -> {
}));
assertEquals("$$foo", Expression.compile("$$foo", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertThrows(IllegalArgumentException.class, () -> Expression.compile("foo$$", MP).evaluate((c, b) -> {
}));
assertEquals("foo$$", Expression.compile("foo$$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertEquals("foo$$bar", Expression.compile("foo$$bar", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertEquals("${foo}", Expression.compile("$${foo}", MP).evaluate((c, b) -> {
}));
assertEquals("$${foo}", Expression.compile("$$${foo}", MP).evaluate((c, b) -> {
}));

assertThrows(IllegalArgumentException.class, () -> Expression.compile("$$${foo}$", MP).evaluate((c, b) -> {
}));
assertEquals("$${foo}$", Expression.compile("$$${foo}$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));
assertEquals("$${foo}$$", Expression.compile("$$${foo}$$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));

assertEquals("foo${bar}", Expression.compile("foo$${bar}", MP).evaluate((c, b) -> {
}));
assertEquals("foo$${bar}", Expression.compile("foo$$${bar}", MP).evaluate((c, b) -> {
}));
assertEquals("foo$$$${bar}", Expression.compile("foo$$$$${bar}", MP).evaluate((c, b) -> {
}));
assertEquals("foo$$$${bar}$$$baz", Expression.compile("foo$$$$${bar}$$$baz", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));
assertEquals("foo$$$$", Expression.compile("foo$$$$", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));
assertEquals("${foo:bar}", Expression.compile("$${foo:bar}", MP).evaluate((c, b) -> {
}));
assertEquals("$${foo:bar}", Expression.compile("$$${foo:bar}", MP).evaluate((c, b) -> {
}));
assertEquals("${foo:}", Expression.compile("$${foo:${bar}}", MP).evaluate((c, b) -> {
}));
assertEquals("${foo:${bar}}", Expression.compile("$${foo:$${bar}}", MP).evaluate((c, b) -> {
}));

assertEquals("", Expression.compile("${foo}", MP).evaluate((c, b) -> {
assertEquals("foo", c.getKey());
}));
assertEquals("", Expression.compile("${foo}${bar}", MP).evaluate((c, b) -> {
if ("foo".equals(c.getKey()))
assertEquals("foo", c.getKey());
if ("bar".equals(c.getKey()))
assertEquals("bar", c.getKey());
}));
assertEquals("foobar", Expression.compile("foo${foo}${bar}bar", MP).evaluate((c, b) -> {
if ("foo".equals(c.getKey()))
assertEquals("foo", c.getKey());
if ("bar".equals(c.getKey()))
assertEquals("bar", c.getKey());
}));
assertEquals("foo${foo}bar", Expression.compile("foo$${foo}${bar}bar", MP).evaluate((c, b) -> {
if ("bar".equals(c.getKey()))
assertEquals("bar", c.getKey());
}));
assertEquals("foo${foo}bar", Expression.compile("foo$${foo${bar}}bar", MP).evaluate((c, b) -> {
if ("bar".equals(c.getKey()))
assertEquals("bar", c.getKey());
}));
assertEquals("", Expression.compile("${}", MP).evaluate((c, b) -> {
assertEquals("", c.getKey());
}));
assertEquals("", Expression.compile("${:}", MP).evaluate((c, b) -> {
assertEquals("", c.getKey());
}));

assertEquals("${foo}", Expression.compile("\\${foo}", MP).evaluate((c, b) -> {
}));
assertEquals("${foo}bar", Expression.compile("\\${foo}bar", MP).evaluate((c, b) -> {
}));
assertEquals("\\$\\{%s}", Expression.compile("\\$\\{%s}", MP).evaluate((c, b) -> {
}));
assertEquals("foo${bar}", Expression.compile("foo\\${bar}", MP).evaluate((c, b) -> {
}));
assertEquals("foo\\\\", Expression.compile("foo\\\\${bar}", MP).evaluate((c, b) -> {
assertEquals("bar", c.getKey());
}));

assertEquals("foo\\$", Expression.compile("foo\\$${bar}", MP).evaluate((c, b) -> {
assertEquals("bar", c.getKey());
}));
assertEquals("foo$${bar}", Expression.compile("foo$\\${bar}", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));
assertEquals("foo$$\\{bar}", Expression.compile("foo$$\\{bar}", MP, LENIENT_SYNTAX).evaluate((c, b) -> {
}));
}
}

0 comments on commit 69ff45b

Please sign in to comment.