Introduce ThingPickerParser.
To ensure that we are extensible from the get-go, this commit introduces the parser aspect of the ThingPicker framework with parsers for the two non-trivial picker implementations. Nothing is wired up yet.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package com.garbagemule.MobArena.things;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class ParserUtil {
|
||||
|
||||
static String extractBetween(String s, char left, char right) {
|
||||
int start = s.indexOf(left);
|
||||
if (start < 0) {
|
||||
throw new IllegalArgumentException("Missing start symbol " + left);
|
||||
}
|
||||
|
||||
int end = s.lastIndexOf(right);
|
||||
if (end < 0) {
|
||||
throw new IllegalArgumentException("Missing end symbol " + right);
|
||||
}
|
||||
|
||||
return s.substring(start + 1, end).trim();
|
||||
}
|
||||
|
||||
static List<String> split(String s) {
|
||||
List<String> result = new ArrayList<>();
|
||||
int start = 0;
|
||||
int parens = 0;
|
||||
int brackets = 0;
|
||||
int curlies = 0;
|
||||
int angles = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == ',') {
|
||||
if (parens == 0 && brackets == 0 && curlies == 0 && angles == 0) {
|
||||
String part = s.substring(start, i).trim();
|
||||
if (!part.isEmpty()) {
|
||||
result.add(part);
|
||||
}
|
||||
start = i + 1;
|
||||
}
|
||||
} else if (c == '(') {
|
||||
parens++;
|
||||
} else if (c == ')') {
|
||||
parens--;
|
||||
if (parens < 0) {
|
||||
throw new IllegalArgumentException("Unmatched right parenthesis )");
|
||||
}
|
||||
} else if (c == '[') {
|
||||
brackets++;
|
||||
} else if (c == ']') {
|
||||
brackets--;
|
||||
if (brackets < 0) {
|
||||
throw new IllegalArgumentException("Unmatched right square bracket ]");
|
||||
}
|
||||
} else if (c == '{') {
|
||||
curlies++;
|
||||
} else if (c == '}') {
|
||||
curlies--;
|
||||
if (curlies < 0) {
|
||||
throw new IllegalArgumentException("Unmatched right curly brace }");
|
||||
}
|
||||
} else if (c == '<') {
|
||||
angles++;
|
||||
} else if (c == '>') {
|
||||
angles--;
|
||||
if (angles < 0) {
|
||||
throw new IllegalArgumentException("Unmatched right angle bracket >");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parens > 0) {
|
||||
throw new IllegalArgumentException("Unmatched left parenthesis (");
|
||||
}
|
||||
if (brackets > 0) {
|
||||
throw new IllegalArgumentException("Unmatched left square bracket [");
|
||||
}
|
||||
if (curlies > 0) {
|
||||
throw new IllegalArgumentException("Unmatched left curly brace {");
|
||||
}
|
||||
if (angles > 0) {
|
||||
throw new IllegalArgumentException("Unmatched left angle bracket <");
|
||||
}
|
||||
if (start == 0) {
|
||||
String part = s.trim();
|
||||
if (!part.isEmpty()) {
|
||||
result.add(part);
|
||||
}
|
||||
} else {
|
||||
String part = s.substring(start).trim();
|
||||
if (!part.isEmpty()) {
|
||||
result.add(part);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.garbagemule.MobArena.things;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RandomThingPickerParser implements ThingPickerParser {
|
||||
|
||||
private final ThingPickerParser parser;
|
||||
private final Random random;
|
||||
|
||||
public RandomThingPickerParser(
|
||||
ThingPickerParser parser,
|
||||
Random random
|
||||
) {
|
||||
this.parser = parser;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingPicker parse(String s) {
|
||||
if (!(s.startsWith("random(") && s.endsWith(")"))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String inner = ParserUtil.extractBetween(s, '(', ')');
|
||||
List<ThingPicker> pickers = ParserUtil.split(inner)
|
||||
.stream()
|
||||
.map(String::trim)
|
||||
.map(parser::parse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (pickers.isEmpty()) {
|
||||
throw new IllegalArgumentException("Nothing to pick from: " + s);
|
||||
}
|
||||
if (pickers.size() == 1) {
|
||||
return pickers.get(0);
|
||||
}
|
||||
|
||||
return new RandomThingPicker(pickers, random);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.garbagemule.MobArena.things;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ThingGroupPickerParser implements ThingPickerParser {
|
||||
|
||||
private final ThingPickerParser parser;
|
||||
|
||||
public ThingGroupPickerParser(ThingPickerParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingPicker parse(String s) {
|
||||
if (!(s.startsWith("all(") && s.endsWith(")"))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String inner = ParserUtil.extractBetween(s, '(', ')');
|
||||
List<ThingPicker> pickers = ParserUtil.split(inner)
|
||||
.stream()
|
||||
.map(String::trim)
|
||||
.map(parser::parse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (pickers.isEmpty()) {
|
||||
throw new IllegalArgumentException("Nothing to group: " + s);
|
||||
}
|
||||
if (pickers.size() == 1) {
|
||||
return pickers.get(0);
|
||||
}
|
||||
|
||||
return new ThingGroupPicker(pickers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.garbagemule.MobArena.things;
|
||||
|
||||
public interface ThingPickerParser {
|
||||
|
||||
/**
|
||||
* Parse the given string, returning a {@link ThingPicker} instance on
|
||||
* success, otherwise null.
|
||||
*
|
||||
* @param s a string to parse
|
||||
* @return an instance of {@link ThingPicker}, or null
|
||||
*/
|
||||
ThingPicker parse(String s);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user