use of net.kyori.adventure.text.minimessage.internal.parser.Token in project adventure by KyoriPowered.
the class MiniMessageParser method parseToTree.
@NotNull
RootNode parseToTree(@NotNull final ContextImpl context) {
final TagResolver combinedResolver = TagResolver.resolver(this.tagResolver, context.extraTags());
final String processedMessage = context.preProcessor().apply(context.message());
final Consumer<String> debug = context.debugOutput();
if (debug != null) {
debug.accept("Beginning parsing message ");
debug.accept(processedMessage);
debug.accept("\n");
}
final TokenParser.TagProvider transformationFactory;
if (debug != null) {
transformationFactory = (name, args, token) -> {
try {
debug.accept("Attempting to match node '");
debug.accept(name);
debug.accept("'");
if (token != null) {
debug.accept(" at column ");
debug.accept(String.valueOf(token.startIndex()));
}
debug.accept("\n");
@Nullable final Tag transformation = combinedResolver.resolve(name, new ArgumentQueueImpl<>(context, args), context);
if (transformation == null) {
debug.accept("Could not match node '");
debug.accept(name);
debug.accept("'\n");
} else {
debug.accept("Successfully matched node '");
debug.accept(name);
debug.accept("' to tag ");
debug.accept(transformation instanceof Examinable ? ((Examinable) transformation).examinableName() : transformation.getClass().getName());
debug.accept("\n");
}
return transformation;
} catch (final ParsingException e) {
if (token != null && e instanceof ParsingExceptionImpl) {
final ParsingExceptionImpl impl = (ParsingExceptionImpl) e;
if (impl.tokens().length == 0) {
impl.tokens(new Token[] { token });
}
}
debug.accept("Could not match node '");
debug.accept(name);
debug.accept("' - ");
debug.accept(e.getMessage());
debug.accept("\n");
return null;
}
};
} else {
transformationFactory = (name, args, token) -> {
try {
return combinedResolver.resolve(name, new ArgumentQueueImpl<>(context, args), context);
} catch (final ParsingException ignored) {
return null;
}
};
}
final Predicate<String> tagNameChecker = name -> {
final String sanitized = TokenParser.TagProvider.sanitizePlaceholderName(name);
return combinedResolver.has(sanitized);
};
final String preProcessed = TokenParser.resolvePreProcessTags(processedMessage, transformationFactory);
context.message(preProcessed);
// Then, once MiniMessage placeholders have been inserted, we can do the real parse
final RootNode root = TokenParser.parse(transformationFactory, tagNameChecker, preProcessed, processedMessage, context.strict());
if (debug != null) {
debug.accept("Text parsed into element tree:\n");
debug.accept(root.toString());
}
return root;
}
use of net.kyori.adventure.text.minimessage.internal.parser.Token in project adventure by KyoriPowered.
the class StringResolvingMatchedTokenConsumer method accept.
@Override
public void accept(final int start, final int end, @NotNull final TokenType tokenType) {
super.accept(start, end, tokenType);
if (tokenType != TokenType.OPEN_TAG) {
// just add it normally, we don't care about other tags
this.builder.append(this.input, start, end);
} else {
// well, now we need to work out if it's a tag or a placeholder!
final String match = this.input.substring(start, end);
final String cleanup = this.input.substring(start + 1, end - 1);
final int index = cleanup.indexOf(SEPARATOR);
final String tag = index == -1 ? cleanup : cleanup.substring(0, index);
// we might care if it's a valid tag!
if (TagInternals.sanitizeAndCheckValidTagName(tag)) {
final List<Token> tokens = tokenize(match);
final List<TagPart> parts = new ArrayList<>();
final List<Token> childs = tokens.isEmpty() ? null : tokens.get(0).childTokens();
if (childs != null) {
for (int i = 1; i < childs.size(); i++) {
parts.add(new TagPart(match, childs.get(i), this.tagProvider));
}
}
// we might care if it's a pre-process!
@Nullable final Tag replacement = this.tagProvider.resolve(TokenParser.TagProvider.sanitizePlaceholderName(tag), parts, tokens.get(0));
if (replacement instanceof PreProcess) {
this.builder.append(Objects.requireNonNull(((PreProcess) replacement).value(), "PreProcess replacements cannot return null"));
return;
}
}
// if we get here, the placeholder wasn't found or was null
this.builder.append(match);
}
}
use of net.kyori.adventure.text.minimessage.internal.parser.Token in project adventure by KyoriPowered.
the class MiniMessageParser method processTokens.
private void processTokens(@NotNull final StringBuilder sb, @NotNull final String richMessage, @NotNull final ContextImpl context, final BiConsumer<Token, StringBuilder> tagHandler) {
final TagResolver combinedResolver = TagResolver.resolver(this.tagResolver, context.extraTags());
final List<Token> root = TokenParser.tokenize(richMessage);
for (final Token token : root) {
switch(token.type()) {
case TEXT:
sb.append(richMessage, token.startIndex(), token.endIndex());
break;
case OPEN_TAG:
case CLOSE_TAG:
case OPEN_CLOSE_TAG:
// extract tag name
if (token.childTokens().isEmpty()) {
sb.append(richMessage, token.startIndex(), token.endIndex());
continue;
}
final String sanitized = TokenParser.TagProvider.sanitizePlaceholderName(token.childTokens().get(0).get(richMessage).toString());
if (combinedResolver.has(sanitized)) {
tagHandler.accept(token, sb);
} else {
sb.append(richMessage, token.startIndex(), token.endIndex());
}
break;
default:
throw new IllegalArgumentException("Unsupported token type " + token.type());
}
}
}
use of net.kyori.adventure.text.minimessage.internal.parser.Token in project adventure by KyoriPowered.
the class TokenListProducingMatchedTokenConsumer method accept.
@Override
public void accept(final int start, final int end, @NotNull final TokenType tokenType) {
super.accept(start, end, tokenType);
if (this.result == null) {
this.result = new ArrayList<>();
}
this.result.add(new Token(start, end, tokenType));
}
use of net.kyori.adventure.text.minimessage.internal.parser.Token in project adventure by KyoriPowered.
the class ElementNode method addChild.
/**
* Adds a child to this node.
*
* <p>This method will attempt to join text tokens together if possible.</p>
*
* @param childNode the child node to add.
* @since 4.10.0
*/
public void addChild(@NotNull final ElementNode childNode) {
final int last = this.children.size() - 1;
if (!(childNode instanceof TextNode) || this.children.isEmpty() || !(this.children.get(last) instanceof TextNode)) {
this.children.add(childNode);
} else {
final TextNode lastNode = (TextNode) this.children.remove(last);
if (lastNode.token().endIndex() == childNode.token().startIndex()) {
final Token replace = new Token(lastNode.token().startIndex(), childNode.token().endIndex(), TokenType.TEXT);
this.children.add(new TextNode(this, replace, lastNode.sourceMessage()));
} else {
// These nodes aren't adjacent in the string, so put the last one back
this.children.add(lastNode);
this.children.add(childNode);
}
}
}
Aggregations