@@ -0,0 +1,1791 @@
+package seedu.address.logic.parser;%0A%0Aimport java.util.HashMap;%0Aimport java.util.Map;%0Aimport java.util.Optional;%0A%0Aimport seedu.address.commons.util.SubstringRange;%0Aimport seedu.address.logic.commands.Command;%0A%0A/**%0A * A parser that implements subcommands (selection of parser based on first word of input)%0A */%0Apublic class SubcommandParser implements Parser%3CCommand%3E %7B%0A%0A    private static final String MSG_NO_COMMAND = %22No command name given%22;%0A%0A    private static final String MSG_UNKNOWN_COMMAND = %22Unknown command: %25s%22;%0A%0A    private Map%3CString, Parser%3C? extends Command%3E%3E parsers = new HashMap%3C%3E();%0A%0A    public SubcommandParser putSubcommand(String name, Parser%3C? extends Command%3E parser) %7B%0A        parsers.put(name, parser);%0A        return this;%0A    %7D%0A%0A    @Override%0A    public Command parse(String str) throws ParseException %7B%0A        final CommandLineScanner scanner = new CommandLineScanner(str);%0A        Optional%3CCommandLineScanner.Argument%3E subcommandArg = scanner.nextArgument();%0A        if (!subcommandArg.isPresent()) %7B%0A            throw new ParseException(MSG_NO_COMMAND, SubstringRange.of(str));%0A        %7D%0A        if (!parsers.containsKey(subcommandArg.get().value)) %7B%0A            throw new ParseException(String.format(MSG_UNKNOWN_COMMAND, subcommandArg.get().value),%0A                                     subcommandArg.get().range);%0A        %7D%0A        Parser%3C? extends Command%3E parser = parsers.get(subcommandArg.get().value);%0A        try %7B%0A            return parser.parse(scanner.getRemainingInput());%0A        %7D catch (ParseException e) %7B%0A            throw new ParseExceptionBuilder(e)%0A                        .prependMessage(subcommandArg.get().value + %22: %22)%0A                        .indentRanges(scanner.getInputPosition())%0A                        .build();%0A        %7D%0A    %7D%0A%0A%7D%0A

implement SubcommandParser