Search in sources :

Example 1 with Token

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;
}
Also used : Tag(net.kyori.adventure.text.minimessage.tag.Tag) ElementNode(net.kyori.adventure.text.minimessage.internal.parser.node.ElementNode) Token(net.kyori.adventure.text.minimessage.internal.parser.Token) RootNode(net.kyori.adventure.text.minimessage.internal.parser.node.RootNode) Predicate(java.util.function.Predicate) TagNode(net.kyori.adventure.text.minimessage.internal.parser.node.TagNode) Collectors(java.util.stream.Collectors) ParsingExceptionImpl(net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl) ArrayList(java.util.ArrayList) Objects(java.util.Objects) Consumer(java.util.function.Consumer) Examinable(net.kyori.examination.Examinable) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) TokenParser(net.kyori.adventure.text.minimessage.internal.parser.TokenParser) Component(net.kyori.adventure.text.Component) MultiLineStringExaminer(net.kyori.examination.string.MultiLineStringExaminer) BiConsumer(java.util.function.BiConsumer) TokenType(net.kyori.adventure.text.minimessage.internal.parser.TokenType) ValueNode(net.kyori.adventure.text.minimessage.internal.parser.node.ValueNode) NotNull(org.jetbrains.annotations.NotNull) Modifying(net.kyori.adventure.text.minimessage.tag.Modifying) Inserting(net.kyori.adventure.text.minimessage.tag.Inserting) TagResolver(net.kyori.adventure.text.minimessage.tag.resolver.TagResolver) RootNode(net.kyori.adventure.text.minimessage.internal.parser.node.RootNode) TagResolver(net.kyori.adventure.text.minimessage.tag.resolver.TagResolver) TokenParser(net.kyori.adventure.text.minimessage.internal.parser.TokenParser) Token(net.kyori.adventure.text.minimessage.internal.parser.Token) Tag(net.kyori.adventure.text.minimessage.tag.Tag) ParsingExceptionImpl(net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl) Nullable(org.jetbrains.annotations.Nullable) Examinable(net.kyori.examination.Examinable) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with Token

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);
    }
}
Also used : PreProcess(net.kyori.adventure.text.minimessage.tag.PreProcess) ArrayList(java.util.ArrayList) Token(net.kyori.adventure.text.minimessage.internal.parser.Token) Tag(net.kyori.adventure.text.minimessage.tag.Tag) Nullable(org.jetbrains.annotations.Nullable) TagPart(net.kyori.adventure.text.minimessage.internal.parser.node.TagPart)

Example 3 with Token

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());
        }
    }
}
Also used : TagResolver(net.kyori.adventure.text.minimessage.tag.resolver.TagResolver) Token(net.kyori.adventure.text.minimessage.internal.parser.Token)

Example 4 with Token

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));
}
Also used : Token(net.kyori.adventure.text.minimessage.internal.parser.Token)

Example 5 with Token

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);
        }
    }
}
Also used : Token(net.kyori.adventure.text.minimessage.internal.parser.Token)

Aggregations

Token (net.kyori.adventure.text.minimessage.internal.parser.Token)6 ArrayList (java.util.ArrayList)3 Tag (net.kyori.adventure.text.minimessage.tag.Tag)3 TagResolver (net.kyori.adventure.text.minimessage.tag.resolver.TagResolver)3 Nullable (org.jetbrains.annotations.Nullable)3 List (java.util.List)2 Objects (java.util.Objects)2 BiConsumer (java.util.function.BiConsumer)2 Consumer (java.util.function.Consumer)2 Predicate (java.util.function.Predicate)2 Collectors (java.util.stream.Collectors)2 Component (net.kyori.adventure.text.Component)2 ParsingExceptionImpl (net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl)2 TokenParser (net.kyori.adventure.text.minimessage.internal.parser.TokenParser)2 TokenType (net.kyori.adventure.text.minimessage.internal.parser.TokenType)2 ElementNode (net.kyori.adventure.text.minimessage.internal.parser.node.ElementNode)2 RootNode (net.kyori.adventure.text.minimessage.internal.parser.node.RootNode)2 TagNode (net.kyori.adventure.text.minimessage.internal.parser.node.TagNode)2 ValueNode (net.kyori.adventure.text.minimessage.internal.parser.node.ValueNode)2 Inserting (net.kyori.adventure.text.minimessage.tag.Inserting)2