Skip to content

Commit

Permalink
Add warning for unsupported delimiter characters
Browse files Browse the repository at this point in the history
Fixes #84
  • Loading branch information
sharwell committed Jul 17, 2016
1 parent 1c5d129 commit 452e401
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 2 deletions.
35 changes: 35 additions & 0 deletions src/org/stringtemplate/v4/STGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ public class STGroup {
TEMPLATE_FILE_EXTENSION = ".st";
}

private static final boolean[] RESERVED_CHARACTERS = new boolean[127];
static {
for (char c = 'a'; c <= 'z'; c++) {
RESERVED_CHARACTERS[c] = true;
}

for (char c = 'A'; c <= 'Z'; c++) {
RESERVED_CHARACTERS[c] = true;
}

for (char c = '0'; c <= '9'; c++) {
RESERVED_CHARACTERS[c] = true;
}

RESERVED_CHARACTERS['@'] = true;
RESERVED_CHARACTERS['-'] = true;
RESERVED_CHARACTERS['_'] = true;
}

/** When we use key as a value in a dictionary, this is how we signify. */
public static final String DICT_KEY = "key";
public static final String DEFAULT_KEY = "default";
Expand Down Expand Up @@ -293,6 +312,22 @@ public synchronized void unload() {
/** Force a load if it makes sense for the group. */
public void load() { }

/**
* Determines if a specified character may be used as a user-specified delimiter.
*
* @param c The character
* @return {@code true} if the character is reserved by the StringTemplate
* language; otherwise, {@code false} if the character may be used as a
* delimiter.
*
* @since 4.0.9
*/
public static boolean isReservedCharacter(char c) {
return c >= 0
&& c < RESERVED_CHARACTERS.length
&& RESERVED_CHARACTERS[c];
}

protected CompiledST lookupImportedTemplate(String name) {
if ( imports.size()==0 ) return null;
for (STGroup g : imports) {
Expand Down
19 changes: 17 additions & 2 deletions src/org/stringtemplate/v4/compiler/Group.g
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,23 @@ groupName returns [String name]
delimiters
: 'delimiters' a=STRING ',' b=STRING
{
group.delimiterStartChar=$a.getText().charAt(1);
group.delimiterStopChar=$b.getText().charAt(1);
boolean supported = true;
char startCharacter = $a.getText().charAt(1);
if (STGroup.isReservedCharacter(startCharacter)) {
group.errMgr.compileTimeError(ErrorType.UNSUPPORTED_DELIMITER, null, $a, String.valueOf(startCharacter));
supported = false;
}

char stopCharacter = $b.getText().charAt(1);
if (STGroup.isReservedCharacter(stopCharacter)) {
group.errMgr.compileTimeError(ErrorType.UNSUPPORTED_DELIMITER, null, $b, String.valueOf(stopCharacter));
supported = false;
}

if (supported) {
group.delimiterStartChar=$a.getText().charAt(1);
group.delimiterStopChar=$b.getText().charAt(1);
}
}
;

Expand Down
1 change: 1 addition & 0 deletions src/org/stringtemplate/v4/misc/ErrorType.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public enum ErrorType {
INVALID_TEMPLATE_NAME("invalid template name or path: %s"),
ANON_ARGUMENT_MISMATCH("anonymous template has %s arg(s) but mapped across %s value(s)"),
REQUIRED_PARAMETER_AFTER_OPTIONAL("required parameters (%s) must appear before optional parameters"),
UNSUPPORTED_DELIMITER("unsupported delimiter character: %s"),

// INTERNAL ERRORS
INTERNAL_ERROR("%s"),
Expand Down
24 changes: 24 additions & 0 deletions test/org/stringtemplate/v4/test/TestGroupSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,30 @@ public class TestGroupSyntax extends BaseTest {
assertEquals(expected, result);
}

/**
* This is a regression test for antlr/stringtemplate4#84.
*/
@Test public void testSetUnsupportedDelimiters_At() throws Exception {
String templates =
"delimiters \"@\", \"@\"" + Misc.newline +
"ta(x) ::= \"[<x>]\"" + Misc.newline;

writeFile(tmpdir, "t.stg", templates);
ErrorBuffer errors = new ErrorBuffer();
STGroup group = new STGroupFile(tmpdir+"/"+"t.stg");
group.setListener(errors);
ST st = group.getInstanceOf("ta");
st.add("x", "hi");
String expected = "[hi]";
String result = st.render();
assertEquals(expected, result);

String expectedErrors = "[t.stg 1:11: unsupported delimiter character: @, "
+ "t.stg 1:16: unsupported delimiter character: @]";
String resultErrors = errors.errors.toString();
assertEquals(expectedErrors, resultErrors);
}

@Test public void testSingleTemplateWithArgs() throws Exception {
String templates =
"t(a,b) ::= \"[<a>]\"" + Misc.newline;
Expand Down

0 comments on commit 452e401

Please sign in to comment.