001/* 002 * PermissionsEx 003 * Copyright (C) zml and PermissionsEx contributors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package ca.stellardrift.permissionsex.minecraft.command.argument; 018 019import ca.stellardrift.permissionsex.minecraft.command.CommandException; 020import cloud.commandframework.arguments.parser.ArgumentParseResult; 021import cloud.commandframework.arguments.parser.ArgumentParser; 022import cloud.commandframework.context.CommandContext; 023import cloud.commandframework.exceptions.parsing.NoInputProvidedException; 024import org.checkerframework.checker.nullness.qual.NonNull; 025 026import java.util.Queue; 027import java.util.regex.Pattern; 028import java.util.regex.PatternSyntaxException; 029 030/** 031 * A parser for regular expressions. 032 * 033 * @param <C> the sender type 034 */ 035public final class PatternParser<C> implements ArgumentParser<C, Pattern> { 036 private final boolean greedy; 037 038 /** 039 * Create a new parser 040 * @param greedy Get whether the argument should consume the remaining input, or just one word 041 */ 042 PatternParser(final boolean greedy) { 043 this.greedy = greedy; 044 } 045 046 @Override 047 public @NonNull ArgumentParseResult<@NonNull Pattern> parse( 048 @NonNull final CommandContext<@NonNull C> commandContext, 049 @NonNull final Queue<@NonNull String> inputQueue 050 ) { 051 if (inputQueue.isEmpty()) { 052 return ArgumentParseResult.failure(new NoInputProvidedException(PatternParser.class, commandContext)); 053 } 054 055 final String input; 056 if (this.greedy) { 057 input = String.join(" ", inputQueue); 058 } else { 059 // TODO: Quoted strings 060 input = inputQueue.peek(); 061 } 062 063 try { 064 final Pattern result = Pattern.compile(input); 065 if (this.greedy) { 066 inputQueue.clear(); 067 } else { 068 inputQueue.remove(); 069 } 070 return ArgumentParseResult.success(result); 071 } catch (final PatternSyntaxException ex) { 072 return ArgumentParseResult.failure(new PatternParseException(ex)); 073 } 074 } 075 076 public boolean greedy() { 077 return this.greedy; 078 } 079 080 @Override 081 public boolean isContextFree() { 082 return true; 083 } 084 085 public static final class PatternParseException extends CommandException { 086 087 private static final long serialVersionUID = -4380135510811949525L; 088 089 private final String pattern; 090 private final String error; 091 private final int index; 092 093 public PatternParseException(final PatternSyntaxException ex) { 094 super(Messages.PATTERN_ERROR_SYNTAX.tr(ex.getPattern(), ex.getIndex(), ex.getDescription())); 095 this.pattern = ex.getPattern(); 096 this.error = ex.getDescription(); 097 this.index = ex.getIndex(); 098 } 099 100 public String pattern() { 101 return this.pattern; 102 } 103 104 public String errorDescription() { 105 return this.error; 106 } 107 108 public int index() { 109 return this.index; 110 } 111 112 } 113 114}