Skip to content

Commit 559d8f3

Browse files
boqDinnerbone
authored andcommitted
Allow single quote in strings
1 parent 447845b commit 559d8f3

File tree

2 files changed

+81
-8
lines changed

2 files changed

+81
-8
lines changed

src/main/java/com/mojang/brigadier/StringReader.java

+23-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
public class StringReader implements ImmutableStringReader {
99
private static final char SYNTAX_ESCAPE = '\\';
10-
private static final char SYNTAX_QUOTE = '"';
10+
private static final char SYNTAX_DOUBLE_QUOTE = '"';
11+
private static final char SYNTAX_SINGLE_QUOTE = '\'';
1112

1213
private final String string;
1314
private int cursor;
@@ -87,6 +88,10 @@ public static boolean isAllowedNumber(final char c) {
8788
return c >= '0' && c <= '9' || c == '.' || c == '-';
8889
}
8990

91+
public static boolean isQuotedStringStart(char c) {
92+
return c == SYNTAX_DOUBLE_QUOTE || c == SYNTAX_SINGLE_QUOTE;
93+
}
94+
9095
public void skipWhitespace() {
9196
while (canRead() && Character.isWhitespace(peek())) {
9297
skip();
@@ -180,16 +185,22 @@ public String readUnquotedString() {
180185
public String readQuotedString() throws CommandSyntaxException {
181186
if (!canRead()) {
182187
return "";
183-
} else if (peek() != SYNTAX_QUOTE) {
188+
}
189+
final char next = peek();
190+
if (!isQuotedStringStart(next)) {
184191
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerExpectedStartOfQuote().createWithContext(this);
185192
}
186193
skip();
194+
return readStringUntil(next);
195+
}
196+
197+
public String readStringUntil(char terminator) throws CommandSyntaxException {
187198
final StringBuilder result = new StringBuilder();
188199
boolean escaped = false;
189200
while (canRead()) {
190201
final char c = read();
191202
if (escaped) {
192-
if (c == SYNTAX_QUOTE || c == SYNTAX_ESCAPE) {
203+
if (c == terminator || c == SYNTAX_ESCAPE) {
193204
result.append(c);
194205
escaped = false;
195206
} else {
@@ -198,7 +209,7 @@ public String readQuotedString() throws CommandSyntaxException {
198209
}
199210
} else if (c == SYNTAX_ESCAPE) {
200211
escaped = true;
201-
} else if (c == SYNTAX_QUOTE) {
212+
} else if (c == terminator) {
202213
return result.toString();
203214
} else {
204215
result.append(c);
@@ -209,11 +220,15 @@ public String readQuotedString() throws CommandSyntaxException {
209220
}
210221

211222
public String readString() throws CommandSyntaxException {
212-
if (canRead() && peek() == SYNTAX_QUOTE) {
213-
return readQuotedString();
214-
} else {
215-
return readUnquotedString();
223+
if (!canRead()) {
224+
return "";
225+
}
226+
final char next = peek();
227+
if (isQuotedStringStart(next)) {
228+
skip();
229+
return readStringUntil(next);
216230
}
231+
return readUnquotedString();
217232
}
218233

219234
public boolean readBoolean() throws CommandSyntaxException {

src/test/java/com/mojang/brigadier/StringReaderTest.java

+58
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,30 @@ public void readQuotedString() throws Exception {
156156
assertThat(reader.getRemaining(), equalTo(""));
157157
}
158158

159+
@Test
160+
public void readSingleQuotedString() throws Exception {
161+
final StringReader reader = new StringReader("'hello world'");
162+
assertThat(reader.readQuotedString(), equalTo("hello world"));
163+
assertThat(reader.getRead(), equalTo("'hello world'"));
164+
assertThat(reader.getRemaining(), equalTo(""));
165+
}
166+
167+
@Test
168+
public void readMixedQuotedString_doubleInsideSingle() throws Exception {
169+
final StringReader reader = new StringReader("'hello \"world\"'");
170+
assertThat(reader.readQuotedString(), equalTo("hello \"world\""));
171+
assertThat(reader.getRead(), equalTo("'hello \"world\"'"));
172+
assertThat(reader.getRemaining(), equalTo(""));
173+
}
174+
175+
@Test
176+
public void readMixedQuotedString_singleInsideDouble() throws Exception {
177+
final StringReader reader = new StringReader("\"hello 'world'\"");
178+
assertThat(reader.readQuotedString(), equalTo("hello 'world'"));
179+
assertThat(reader.getRead(), equalTo("\"hello 'world'\""));
180+
assertThat(reader.getRemaining(), equalTo(""));
181+
}
182+
159183
@Test
160184
public void readQuotedString_empty() throws Exception {
161185
final StringReader reader = new StringReader("");
@@ -242,6 +266,40 @@ public void readQuotedString_invalidEscape() throws Exception {
242266
}
243267
}
244268

269+
@Test
270+
public void readQuotedString_invalidQuoteEscape() throws Exception {
271+
try {
272+
new StringReader("'hello\\\"\'world").readQuotedString();
273+
} catch (final CommandSyntaxException ex) {
274+
assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape()));
275+
assertThat(ex.getCursor(), is(7));
276+
}
277+
}
278+
279+
@Test
280+
public void readString_noQuotes() throws Exception {
281+
final StringReader reader = new StringReader("hello world");
282+
assertThat(reader.readString(), equalTo("hello"));
283+
assertThat(reader.getRead(), equalTo("hello"));
284+
assertThat(reader.getRemaining(), equalTo(" world"));
285+
}
286+
287+
@Test
288+
public void readString_singleQuotes() throws Exception {
289+
final StringReader reader = new StringReader("'hello world'");
290+
assertThat(reader.readString(), equalTo("hello world"));
291+
assertThat(reader.getRead(), equalTo("'hello world'"));
292+
assertThat(reader.getRemaining(), equalTo(""));
293+
}
294+
295+
@Test
296+
public void readString_doubleQuotes() throws Exception {
297+
final StringReader reader = new StringReader("\"hello world\"");
298+
assertThat(reader.readString(), equalTo("hello world"));
299+
assertThat(reader.getRead(), equalTo("\"hello world\""));
300+
assertThat(reader.getRemaining(), equalTo(""));
301+
}
302+
245303
@Test
246304
public void readInt() throws Exception {
247305
final StringReader reader = new StringReader("1234567890");

0 commit comments

Comments
 (0)