Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace SkriptParser ExprInfo Cache #6594

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 7 additions & 55 deletions src/main/java/ch/njol/skript/lang/SkriptParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import ch.njol.skript.patterns.MalformedPatternException;
import ch.njol.skript.patterns.PatternCompiler;
import ch.njol.skript.patterns.SkriptPattern;
import ch.njol.skript.patterns.TypePatternElement;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.Utils;
import ch.njol.util.Kleenean;
Expand Down Expand Up @@ -119,6 +120,8 @@ public SkriptParser(SkriptParser other, String expr) {
public static final String WILDCARD = "[^\"]*?(?:\"[^\"]*?\"[^\"]*?)*?";

public static class ParseResult {
@Nullable
public SkriptPattern source;
public Expression<?>[] exprs;
public List<MatchResult> regexes = new ArrayList<>(1);
public String expr;
Expand Down Expand Up @@ -236,20 +239,18 @@ private <T extends SyntaxElement> T parse(Iterator<? extends SyntaxElementInfo<?

}
if (parseResult != null) {
int startIndex = -1;
for (int i = 0; (startIndex = nextUnescaped(pattern, '%', startIndex + 1)) != -1; i++) {
int endIndex = nextUnescaped(pattern, '%', startIndex + 1);
assert parseResult.source != null; // parse results from parse_i have a source
List<TypePatternElement> types = parseResult.source.getElements(TypePatternElement.class);
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
for (int i = 0; i < parseResult.exprs.length; i++) {
if (parseResult.exprs[i] == null) {
String name = pattern.substring(startIndex + 1, endIndex);
ExprInfo exprInfo = getExprInfo(name);
ExprInfo exprInfo = types.get(i).getExprInfo();
if (!exprInfo.isOptional) {
DefaultExpression<?> expr = getDefaultExpression(exprInfo, info.patterns[patternIndex]);
if (!expr.init())
continue patternsLoop;
parseResult.exprs[i] = expr;
}
}
startIndex = endIndex;
}
T element = info.getElementClass().newInstance();
if (element.init(parseResult.exprs, patternIndex, getParser().getHasDelayBefore(), parseResult)) {
Expand Down Expand Up @@ -1374,55 +1375,6 @@ public ExprInfo(int length) {
public int time = 0;
}

private static final Map<String,ExprInfo> exprInfoCache = new HashMap<>();

private static ExprInfo getExprInfo(String string) throws IllegalArgumentException, SkriptAPIException {
ExprInfo exprInfo = exprInfoCache.get(string);
if (exprInfo == null) {
exprInfo = createExprInfo(string);
exprInfoCache.put(string, exprInfo);
}

return exprInfo;
}

private static ExprInfo createExprInfo(String string) throws IllegalArgumentException, SkriptAPIException {
ExprInfo exprInfo = new ExprInfo(StringUtils.count(string, '/') + 1);
int caret = 0;
flags:
do {
switch (string.charAt(caret)) {
case '-':
exprInfo.isOptional = true;
break;
case '*':
exprInfo.flagMask &= ~PARSE_EXPRESSIONS;
break;
case '~':
exprInfo.flagMask &= ~PARSE_LITERALS;
break;
default:
break flags;
}
++caret;
} while (true);
int atSign = string.indexOf('@', caret);
if (atSign != -1) {
exprInfo.time = Integer.parseInt(string.substring(atSign + 1));
string = string.substring(caret, atSign);
} else {
string = string.substring(caret);
}
String[] classes = string.split("/");
assert classes.length == exprInfo.classes.length;
for (int i = 0; i < classes.length; i++) {
NonNullPair<String, Boolean> plural = Utils.getEnglishPlural("" + classes[i]);
exprInfo.classes[i] = Classes.getClassInfo(plural.getFirst());
exprInfo.isPlural[i] = plural.getSecond();
}
return exprInfo;
}

/**
* @see ParserInstance#get()
*/
Expand Down
26 changes: 16 additions & 10 deletions src/main/java/ch/njol/skript/patterns/MatchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import com.google.common.base.MoreObjects;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -31,6 +32,8 @@
*/
public class MatchResult {

SkriptPattern source;

int exprOffset;

Expression<?>[] expressions = new Expression[0];
Expand All @@ -45,6 +48,7 @@ public class MatchResult {

public MatchResult copy() {
MatchResult matchResult = new MatchResult();
matchResult.source = this.source;
matchResult.exprOffset = this.exprOffset;
matchResult.expressions = this.expressions.clone();
matchResult.expr = this.expr;
Expand All @@ -58,6 +62,7 @@ public MatchResult copy() {

public ParseResult toParseResult() {
ParseResult parseResult = new ParseResult(expr, expressions);
parseResult.source = source;
parseResult.regexes.addAll(regexResults);
parseResult.mark = mark;
parseResult.tags.addAll(tags);
Expand Down Expand Up @@ -86,16 +91,17 @@ public List<java.util.regex.MatchResult> getRegexResults() {

@Override
public String toString() {
return "MatchResult{" +
"exprOffset=" + exprOffset +
", expressions=" + Arrays.toString(expressions) +
", expr='" + expr + '\'' +
", mark=" + mark +
", tags=" + tags +
", regexResults=" + regexResults +
", parseContext=" + parseContext +
", flags=" + flags +
'}';
return MoreObjects.toStringHelper(this)
.add("source", source)
.add("exprOffset", exprOffset)
.add("expressions", Arrays.toString(expressions))
.add("expr", expr)
.add("mark", mark)
.add("tags", tags)
.add("regexResults", regexResults)
.add("parseContext", parseContext)
.add("flags", flags)
.toString();
}

}
46 changes: 46 additions & 0 deletions src/main/java/ch/njol/skript/patterns/SkriptPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.lang.SkriptParser;
import com.google.common.collect.ImmutableList;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
Expand All @@ -33,6 +34,8 @@ public class SkriptPattern {
private final int expressionAmount;

private final String[] keywords;
@Nullable
private List<TypePatternElement> types;

public SkriptPattern(PatternElement first, int expressionAmount) {
this.first = first;
Expand All @@ -51,6 +54,7 @@ public MatchResult match(String expr, int flags, ParseContext parseContext) {
expr = expr.trim();

MatchResult matchResult = new MatchResult();
matchResult.source = this;
matchResult.expr = expr;
matchResult.expressions = new Expression[expressionAmount];
matchResult.parseContext = parseContext;
Expand Down Expand Up @@ -147,4 +151,46 @@ private static int countNonNullTypes(PatternElement patternElement) {
return count;
}

/**
* A method to obtain a list of all pattern elements of a specified type that are represented by this SkriptPattern.
* @param type The type of pattern elements to obtain.
* @return A list of all pattern elements of the specified type represented by this SkriptPattern.
* @param <T> The type of pattern element.
*/
public <T extends PatternElement> List<T> getElements(Class<T> type) {
if (type == TypePatternElement.class) {
if (types == null) {
types = ImmutableList.copyOf(getElements(TypePatternElement.class, first, new ArrayList<>()));
}
Moderocky marked this conversation as resolved.
Show resolved Hide resolved
//noinspection unchecked - checked with type == TypePatternElement
return (List<T>) types;
}
return getElements(type, first, new ArrayList<>());
}

/**
* A method to obtain a list of all pattern elements of a specified type (from a starting element).
* @param type The type of pattern elements to obtain.
* @param element The element to start searching for other elements from (this will unwrap certain elements).
* @param elements A list to add matching elements to.
* @return A list of all pattern elements of a specified type (from a starting element).
* @param <T> The type of pattern element.
*/
private static <T extends PatternElement> List<T> getElements(Class<T> type, PatternElement element, List<T> elements) {
while (element != null) {
if (element instanceof ChoicePatternElement) {
((ChoicePatternElement) element).getPatternElements().forEach(e -> getElements(type, e, elements));
} else if (element instanceof GroupPatternElement) {
getElements(type, ((GroupPatternElement) element).getPatternElement(), elements);
} else if (element instanceof OptionalPatternElement) {
getElements(type, ((OptionalPatternElement) element).getPatternElement(), elements);
} else if (type.isInstance(element)) {
//noinspection unchecked - it is checked with isInstance
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved
elements.add((T) element);
}
element = element.originalNext;
}
return elements;
}

}
Loading