Skip to content

Commit

Permalink
Fix a few more bugs around parsing. Still not working for lists due t…
Browse files Browse the repository at this point in the history
…o a lin-bus issue
  • Loading branch information
me4502 committed Sep 1, 2023
1 parent ee7fe91 commit 8fe5ec2
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
56 changes: 56 additions & 0 deletions worldedit-core/src/main/java/com/sk89q/util/StringUtil.java
Expand Up @@ -24,6 +24,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* String utilities.
Expand Down Expand Up @@ -305,10 +307,27 @@ public static <T extends Enum<?>> T lookup(Map<String, T> lookup, String name, b
return type;
}

private static int indexOfRegEx(String input, Pattern pattern) {
Matcher m = pattern.matcher(input);
return m.find() ? m.start() : -1;
}

private static int lastIndexOfRegEx(String input, Pattern pattern) {
// Reverse the input string and run a forwards search on the backwards string
StringBuilder builder = new StringBuilder(input).reverse();
int reverseIndex = indexOfRegEx(builder.toString(), pattern);

// If it wasn't found return -1, otherwise take length - index - 1.
return (reverseIndex == -1) ? -1 : (input.length() - reverseIndex - 1);
}

public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen, char quoteClose) {
return parseListInQuotes(input, delimiter, quoteOpen, quoteClose, false);
}

public static Pattern BLOCK_QUOTE_OPEN_PATTERN = Pattern.compile("[\\[{]");
public static Pattern BLOCK_QUOTE_CLOSE_PATTERN = Pattern.compile("[]}]");

public static List<String> parseListInQuotes(String[] input, char delimiter, char quoteOpen, char quoteClose, boolean appendLeftover) {
List<String> parsableBlocks = new ArrayList<>();
StringBuilder buffer = new StringBuilder();
Expand All @@ -331,4 +350,41 @@ public static List<String> parseListInQuotes(String[] input, char delimiter, cha

return parsableBlocks;
}

public static List<String> parseListInQuotes(String[] input, char delimiter, char[] quoteOpen, char[] quoteClose, boolean appendLeftover) {
List<String> parsableBlocks = new ArrayList<>();
StringBuilder buffer = new StringBuilder();
int quotes = quoteOpen.length;
if (quotes != quoteClose.length) {
throw new Error("Mismatched quoteOpen and quoteClose lengths");
}
for (String split : input) {
boolean quoteHandled = false;
for (int i = 0; i < quotes; i++) {
if (split.indexOf(quoteOpen[i]) != -1 && split.indexOf(quoteClose[i]) == -1) {
buffer.append(split).append(delimiter);
quoteHandled = true;
break;
} else if (split.indexOf(quoteClose[i]) != -1 && split.indexOf(quoteOpen[i]) == -1) {
buffer.append(split);
parsableBlocks.add(buffer.toString());
buffer = new StringBuilder();
quoteHandled = true;
break;
}
}
if (!quoteHandled) {
if (buffer.length() == 0) {
parsableBlocks.add(split);
} else {
buffer.append(split).append(delimiter);
}
}
}
if (appendLeftover && buffer.length() != 0) {
parsableBlocks.add(buffer.delete(buffer.length() - 1, buffer.length()).toString());
}

return parsableBlocks;
}
}
Expand Up @@ -59,7 +59,7 @@ public BlockFactory(WorldEdit worldEdit) {
public Set<BaseBlock> parseFromListInput(String input, ParserContext context) throws InputParseException {
Set<BaseBlock> blocks = new HashSet<>();
String[] splits = input.split(",");
for (String token : StringUtil.parseListInQuotes(splits, ',', '[', ']', true)) {
for (String token : StringUtil.parseListInQuotes(splits, ',', new char[] {'[', '{' }, new char[] {']', '}'}, true)) {
blocks.add(parseFromInput(token, context));
}
return blocks;
Expand Down
Expand Up @@ -289,7 +289,7 @@ private BaseBlock parseLogic(String input, ParserContext context) throws InputPa

int stateStart = blockAndExtraData[0].indexOf('[');
int nbtStart = blockAndExtraData[0].indexOf('{');
int typeEnd = stateStart == -1 ? nbtStart : stateStart;
int typeEnd = stateStart == -1 ? nbtStart : nbtStart == -1 ? stateStart : Math.min(nbtStart, stateStart);

if (typeEnd == -1) {
typeString = blockAndExtraData[0];
Expand All @@ -298,7 +298,7 @@ private BaseBlock parseLogic(String input, ParserContext context) throws InputPa
}

String stateString = null;
if (stateStart != -1) {
if (stateStart != -1 && (nbtStart == -1 || stateStart < nbtStart)) {
if (stateStart + 1 >= blockAndExtraData[0].length()) {
throw new InputParseException(TranslatableComponent.of("worldedit.error.parser.hanging-lbracket", TextComponent.of(stateStart)));
}
Expand Down Expand Up @@ -434,7 +434,7 @@ private BaseBlock parseLogic(String input, ParserContext context) throws InputPa
return baseBlock;
}

if (DeprecationUtil.isSign(blockType)) {
if (DeprecationUtil.isSign(blockType) && blockAndExtraData.length > 1) {
// Allow special sign text syntax
String[] text = new String[4];
text[0] = blockAndExtraData.length > 1 ? blockAndExtraData[1] : "";
Expand All @@ -444,7 +444,7 @@ private BaseBlock parseLogic(String input, ParserContext context) throws InputPa
@SuppressWarnings("deprecation")
SignBlock signBlock = new SignBlock(state, text);
return signBlock;
} else if (blockType == BlockTypes.SPAWNER) {
} else if (blockType == BlockTypes.SPAWNER && (blockAndExtraData.length > 1 || blockNbtData != null)) {
// Allow setting mob spawn type
String mobName;
if (blockAndExtraData.length > 1) {
Expand All @@ -463,7 +463,7 @@ private BaseBlock parseLogic(String input, ParserContext context) throws InputPa
@SuppressWarnings("deprecation")
MobSpawnerBlock mobSpawnerBlock = new MobSpawnerBlock(state, mobName);
return mobSpawnerBlock;
} else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) {
} else if ((blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) && (blockAndExtraData.length > 1 || blockNbtData != null)) {
// allow setting type/player/rotation
if (blockAndExtraData.length <= 1) {
@SuppressWarnings("deprecation")
Expand Down
Expand Up @@ -43,7 +43,7 @@ public RandomPatternParser(WorldEdit worldEdit) {
@Override
public Stream<String> getSuggestions(String input, ParserContext context) {
String[] splits = input.split(",", -1);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', '[', ']', true);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', new char[] {'[', '{' }, new char[] {']', '}'}, true);
// get suggestions for the last token only
String percent = null;
String token = patterns.get(patterns.size() - 1);
Expand All @@ -65,7 +65,7 @@ public Pattern parseFromInput(String input, ParserContext context) throws InputP
RandomPattern randomPattern = new RandomPattern();

String[] splits = input.split(",", -1);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', '[', ']', true);
List<String> patterns = StringUtil.parseListInQuotes(splits, ',', new char[] {'[', '{' }, new char[] {']', '}'}, true);
if (patterns.size() == 1) {
return null; // let a 'single'-pattern parser handle it
}
Expand Down

0 comments on commit 8fe5ec2

Please sign in to comment.