<@ and </@ is now allowed in String literals that contain ${exp}, and will be part of the literal as is. Earlier it was a syntactical error.
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index e234e90..f65f4c5 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
Binary files differ
diff --git a/src/manual/book.xml b/src/manual/book.xml
index b8bc656..6decbd9 100644
--- a/src/manual/book.xml
+++ b/src/manual/book.xml
@@ -25810,6 +25810,14 @@
keeping the exact class can be important in some
applications.</para>
</listitem>
+
+ <listitem>
+ <para><literal><@</literal> and <literal></@</literal> is
+ now allowed in String literals that contain
+ <literal>${<replaceable>exp</replaceable>}</literal>, and will
+ be part of the literal as is. Earlier it was a syntactical
+ error.</para>
+ </listitem>
</itemizedlist>
</section>
diff --git a/src/test/java/freemarker/core/StringLiteralInterpolationTest.java b/src/test/java/freemarker/core/StringLiteralInterpolationTest.java
index 6abe579..e6d86e4 100644
--- a/src/test/java/freemarker/core/StringLiteralInterpolationTest.java
+++ b/src/test/java/freemarker/core/StringLiteralInterpolationTest.java
@@ -34,6 +34,20 @@
assertOutput("<#assign x = 1>${'${x} ${x}'}", "1 1");
assertOutput("<#assign x = 1>${'$\\{x}'}", "${x}");
assertOutput("<#assign x = 1>${'$\\{x} $\\{x}'}", "${x} ${x}");
+ assertOutput("<#assign x = 1>${'<#-- not a comment -->${x}'}", "<#-- not a comment -->1");
+ assertOutput("<#assign x = 1>${'<#-- not a comment -->$\\{x}'}", "<#-- not a comment -->${x}");
+ assertOutput("<#assign x = 1>${'<@x/>${x}'}", "<@x/>1");
+ assertOutput("<#assign x = 1>${'<@x/>$\\{x}'}", "<@x/>${x}");
+ assertOutput("<#assign x = 1>${'<@ ${x}<@'}", "<@ 1<@");
+ assertOutput("<#assign x = 1>${'<@ $\\{x}<@'}", "<@ ${x}<@");
+ assertOutput("<#assign x = 1>${'</@x>${x}'}", "</@x>1");
+ assertOutput("<#assign x = 1>${'</@x>$\\{x}'}", "</@x>${x}");
+ assertOutput("<#assign x = 1>${'</@ ${x}</@'}", "</@ 1</@");
+ assertOutput("<#assign x = 1>${'</@ $\\{x}</@'}", "</@ ${x}</@");
+ assertOutput("<#assign x = 1>${'[@ ${x}'}", "[@ 1");
+ assertOutput("<#assign x = 1>${'[@ $\\{x}'}", "[@ ${x}");
+ assertOutput("<#assign x = 1>${'<#assign x = 2> ${x}'}", "<#assign x = 2> 1");
+ assertOutput("<#assign x = 1>${'<#assign x = 2> $\\{x}'}", "<#assign x = 2> ${x}");
}
/**