package main.options.parser; import java.lang.reflect.Field; import java.util.NoSuchElementException; import java.util.Scanner; import hextostring.replacement.Replacement; import hextostring.replacement.ReplacementType; import hextostring.replacement.Replacements; import main.options.Options; /** * LL1 parser for command-line replacements. * * @author Maxime PIA */ public class ReplacementsParser extends FullArgumentParser<Replacements> { public ReplacementsParser(Options opts, Field f, String argument) { super(opts, f, argument); } @Override protected Replacements getArgumentValue(String arg) throws IncompatibleParserException { Replacements replacements = null; Scanner sc = new Scanner(checkArgumentAndGetValue(arg)); try { replacements = readReplacements(sc); } catch (NoSuchElementException | IllegalArgumentException e) { e.printStackTrace(); throw e; } finally { sc.close(); } return replacements; } private Replacements readReplacements(Scanner sc) { Replacements replacements = new Replacements(); while (sc.hasNext()) { replacements.add(readReplacement(sc)); if (sc.hasNext()) { sc.findInLine(","); } } return replacements; } private Replacement readReplacement(Scanner sc) { boolean isSequenceHexadecimal = readIsHexadecimal(sc); String sequence = readString(sc); sequence = sequence.substring(1, sequence.length() - 1); sc.findInLine(">"); boolean isReplacementHexadecimal = readIsHexadecimal(sc); String replacement = readString(sc); replacement = replacement.substring(1, replacement.length() - 1); if (!isSequenceHexadecimal && isReplacementHexadecimal) { throw new IllegalArgumentException("Hexadecimal cannot be a " + "replacement of string"); } ReplacementType type = isReplacementHexadecimal ? ReplacementType.HEX2HEX : isSequenceHexadecimal ? ReplacementType.HEX2STR : ReplacementType.STR2STR; boolean esc = readIsEscapeChar(sc); boolean reg = readIsRegexp(sc); return new Replacement(sequence, replacement, esc, reg, type); } private boolean readIsHexadecimal(Scanner sc) { return checkNextAndRead(sc, "0x"); } private String readString(Scanner sc) { return sc.findInLine("([\"]([^\\\\\"]*([\\\\].)*)*[\"])"); } private boolean readIsEscapeChar(Scanner sc) { return checkNextAndRead(sc, "e"); } private boolean readIsRegexp(Scanner sc) { return checkNextAndRead(sc, "r"); } private boolean checkNextAndRead(Scanner sc, String s) { // s must not be a pattern return sc.findWithinHorizon(s, s.length()) != null; } }