Compare commits

...

1 commit

Author SHA1 Message Date
boq
b0c50823f5 Allow single quote in strings 2019-01-29 14:10:21 +01:00
2 changed files with 81 additions and 8 deletions

View file

@ -7,7 +7,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
public class StringReader implements ImmutableStringReader {
private static final char SYNTAX_ESCAPE = '\\';
private static final char SYNTAX_QUOTE = '"';
private static final char SYNTAX_DOUBLE_QUOTE = '"';
private static final char SYNTAX_SINGLE_QUOTE = '\'';
private final String string;
private int cursor;
@ -87,6 +88,10 @@ public class StringReader implements ImmutableStringReader {
return c >= '0' && c <= '9' || c == '.' || c == '-';
}
public static boolean isQuotedStringStart(char c) {
return c == SYNTAX_DOUBLE_QUOTE || c == SYNTAX_SINGLE_QUOTE;
}
public void skipWhitespace() {
while (canRead() && Character.isWhitespace(peek())) {
skip();
@ -180,16 +185,22 @@ public class StringReader implements ImmutableStringReader {
public String readQuotedString() throws CommandSyntaxException {
if (!canRead()) {
return "";
} else if (peek() != SYNTAX_QUOTE) {
}
final char next = peek();
if (!isQuotedStringStart(next)) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerExpectedStartOfQuote().createWithContext(this);
}
skip();
return readStringUntil(next);
}
public String readStringUntil(char terminator) throws CommandSyntaxException {
final StringBuilder result = new StringBuilder();
boolean escaped = false;
while (canRead()) {
final char c = read();
if (escaped) {
if (c == SYNTAX_QUOTE || c == SYNTAX_ESCAPE) {
if (c == terminator || c == SYNTAX_ESCAPE) {
result.append(c);
escaped = false;
} else {
@ -198,7 +209,7 @@ public class StringReader implements ImmutableStringReader {
}
} else if (c == SYNTAX_ESCAPE) {
escaped = true;
} else if (c == SYNTAX_QUOTE) {
} else if (c == terminator) {
return result.toString();
} else {
result.append(c);
@ -209,11 +220,15 @@ public class StringReader implements ImmutableStringReader {
}
public String readString() throws CommandSyntaxException {
if (canRead() && peek() == SYNTAX_QUOTE) {
return readQuotedString();
} else {
return readUnquotedString();
if (!canRead()) {
return "";
}
final char next = peek();
if (isQuotedStringStart(next)) {
skip();
return readStringUntil(next);
}
return readUnquotedString();
}
public boolean readBoolean() throws CommandSyntaxException {

View file

@ -156,6 +156,30 @@ public class StringReaderTest {
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readSingleQuotedString() throws Exception {
final StringReader reader = new StringReader("'hello world'");
assertThat(reader.readQuotedString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("'hello world'"));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readMixedQuotedString_doubleInsideSingle() throws Exception {
final StringReader reader = new StringReader("'hello \"world\"'");
assertThat(reader.readQuotedString(), equalTo("hello \"world\""));
assertThat(reader.getRead(), equalTo("'hello \"world\"'"));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readMixedQuotedString_singleInsideDouble() throws Exception {
final StringReader reader = new StringReader("\"hello 'world'\"");
assertThat(reader.readQuotedString(), equalTo("hello 'world'"));
assertThat(reader.getRead(), equalTo("\"hello 'world'\""));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readQuotedString_empty() throws Exception {
final StringReader reader = new StringReader("");
@ -242,6 +266,40 @@ public class StringReaderTest {
}
}
@Test
public void readQuotedString_invalidQuoteEscape() throws Exception {
try {
new StringReader("'hello\\\"\'world").readQuotedString();
} catch (final CommandSyntaxException ex) {
assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape()));
assertThat(ex.getCursor(), is(7));
}
}
@Test
public void readString_noQuotes() throws Exception {
final StringReader reader = new StringReader("hello world");
assertThat(reader.readString(), equalTo("hello"));
assertThat(reader.getRead(), equalTo("hello"));
assertThat(reader.getRemaining(), equalTo(" world"));
}
@Test
public void readString_singleQuotes() throws Exception {
final StringReader reader = new StringReader("'hello world'");
assertThat(reader.readString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("'hello world'"));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readString_doubleQuotes() throws Exception {
final StringReader reader = new StringReader("\"hello world\"");
assertThat(reader.readString(), equalTo("hello world"));
assertThat(reader.getRead(), equalTo("\"hello world\""));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readInt() throws Exception {
final StringReader reader = new StringReader("1234567890");