Skip to content

Commit

Permalink
Merge pull request #51 from ziyi105/use-pattern-and-matcher-in-parser
Browse files Browse the repository at this point in the history
Use pattern and matcher in parser
  • Loading branch information
DextheChik3n authored Oct 17, 2023
2 parents a60c6f8 + fe4ae66 commit 2df1928
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/main/java/seedu/duke/command/AddDishCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class AddDishCommand extends Command {
public AddDishCommand(Dish dish) {
this.dish = dish;
}

@Override
public void execute(Menu menu, Ui ui) {
menu.addDish(dish);
Expand Down
9 changes: 0 additions & 9 deletions src/main/java/seedu/duke/command/DeleteDishCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@ public class DeleteDishCommand extends Command {
+ "Parameters: INDEX\n"
+ "Example: " + COMMAND_WORD + " 1";

/**
* Constructor for DeleteDishCommand
*
* @param index index of menu item to be deleted
*/
public DeleteDishCommand(int index) {
this.index = index;
}

@Override
public void execute(Menu menu, Ui ui) {
Dish selectedDish = menu.getMenuItemsList().get(index - Ui.OFFSET_LIST_INDEX);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/seedu/duke/command/ListMenuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public class ListMenuCommand extends Command {
public static final String COMMAND_WORD = "list";
private static final DecimalFormat dollarValue = new DecimalFormat("0.00");

/**
* Iterates through the menu arraylist, outputting the dish name and dish price.
*
Expand Down
120 changes: 99 additions & 21 deletions src/main/java/seedu/duke/parser/Parser.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,131 @@
package seedu.duke.parser;

import seedu.duke.command.AddDishCommand;
import seedu.duke.data.Menu;

import seedu.duke.command.Command;
import seedu.duke.command.AddDishCommand;
import seedu.duke.command.DeleteDishCommand;
import seedu.duke.command.ExitCommand;
import seedu.duke.command.IncorrectCommand;
import seedu.duke.command.ListIngredientCommand;
import seedu.duke.command.ListMenuCommand;
import seedu.duke.data.Menu;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.ParseException;

/**
* Parse everything received from the users on terminal
* into a format that can be interpreted by other core classes
*/
public class Parser {
public static final Pattern COMMAND_ARGUMENT_FORMAT = Pattern.compile("(?<commandWord>\\S+)(?<arguments>.*)");

// Command Argument Patterns
private static final String ADD_ARGUMENT_STRING = "add name/(\\w+) price/(\\d+(\\.\\d+)?)" +
" (ingredient/\\w+ qty/\\d+(\\.\\d+)?(?:, )?)+";
private static final String LIST_INGREDIENTS_ARGUMENT_STRING = "(\\d+)";
private static final String DELETE_ARGUMENT_STRING = "(\\d+)";
private static final String EDIT_PRICE_ARGUMENT_STRING = "index/(\\d+) price/(\\d+(\\.\\d+)?)";

/**
* Parses user input into command for execution.
* Parse userInput and group it under commandWord and arguments
* use commandWord to find the matching command and prepare the command
*
* @param userInput full user input string
* @param userInput full user input
* @param menu The arraylist object created that stores current tasks
* @return the command based on the user input
* @return command requested by the user
*/
public static Command parseCommand(Menu menu, String userInput) {
String[] command = userInput.split(" ");
switch (command[0].toLowerCase()) {
case ListMenuCommand.COMMAND_WORD:
return new ListMenuCommand();
case ListIngredientCommand.COMMAND_WORD:
return prepareListIngredient(userInput);
public Command parseCommand(Menu menu, String userInput) {
final Matcher matcher = COMMAND_ARGUMENT_FORMAT.matcher(userInput.trim());
if (!matcher.matches()) {
return new IncorrectCommand("Incorrect command format!");
}

final String commandWord = matcher.group("commandWord");
final String arguments = matcher.group("arguments");

switch (commandWord) {

case AddDishCommand.COMMAND_WORD:
return prepareAdd(arguments);

case DeleteDishCommand.COMMAND_WORD:
return prepareDelete(userInput);
return prepareDelete(arguments);

case ListIngredientCommand.COMMAND_WORD:
return prepareListIngredient(arguments);

case ListMenuCommand.COMMAND_WORD:
return prepareListMenu();

case ExitCommand.COMMAND_WORD:
return new ExitCommand();
case AddDishCommand.COMMAND_WORD:
//return new AddDishCommand();
return new IncorrectCommand("DEXTER DO WORK");

default:
return new IncorrectCommand("Your command has left me scratching my virtual head. " +
"Let's try that again, shall we?");
}
}

// All prepareCommand Classes
private Command prepareListMenu() {
// To be implemented by xx
return null;
}

private Command prepareAdd(String arguments) {
final Pattern ADD_ARGUMENT_PATTERN = Pattern.compile(ADD_ARGUMENT_STRING);
Matcher matcher = ADD_ARGUMENT_PATTERN.matcher(arguments);

// Checks whether the overall pattern of add arguments is correct
if (matcher.matches()) {
return new IncorrectCommand("Error: Missing arguments for the add command.");
}

try {
// To retrieve specific arguments from arguments
String dishName = matcher.group(1);
float price = Float.parseFloat(matcher.group(2));

// Capture the list of ingredients and quantities
ArrayList<String> ingredients = new ArrayList<>();
ArrayList<String> quantities = new ArrayList<>();

// Find all matches for ingredients and quantities
Pattern ingredientPattern = Pattern.compile("ingredient/([A-Za-z]+) qty/([A-Za-z]+)");
Matcher ingredientMatcher = ingredientPattern.matcher(arguments);

while (ingredientMatcher.find()) {
String ingredient = ingredientMatcher.group(1);
String quantity = ingredientMatcher.group(2);
ingredients.add(ingredient);
quantities.add(quantity);
}

// Todo: Implement error handling for checking the size of ingredients quantities
// I am not sure if this is necessary as we have already checked
// the overall command pattern in line 62

// Todo: Add the attributes in AddDishCommand
// Todo: Overload the constructor of Dish such that
// it can take in ingredients list and quantities list
// and create an arrayList of ingredient objects
// return new AddDishCommand(dishName, price, ingredients, quantities);
} catch (Exception e) {
// Todo: Add error handling for invalid price type etc.
}

return new IncorrectCommand("The specific details are " +
"to be implemented by Dexter");
}

/**
* Parses arguments in the context of the ListIngredient command.
* @param userInput arguments string to parse as index number
* @return the prepared command
*/
* Parses arguments in the context of the ListIngredient command.
* @param userInput arguments string to parse as index number
* @return the prepared command
*/
private static Command prepareListIngredient(String userInput) {
try {
final int listIndex = parseArgsAsDisplayedIndex(userInput, ListIngredientCommand.COMMAND_WORD);
Expand All @@ -68,7 +146,7 @@ private static Command prepareListIngredient(String userInput) {
private static Command prepareDelete(String userInput) {
try {
final int listIndex = parseArgsAsDisplayedIndex(userInput, DeleteDishCommand.COMMAND_WORD);
return new DeleteDishCommand(listIndex);
return new DeleteDishCommand();
} catch (ParseException e) {
return new IncorrectCommand("MESSAGE_INVALID_COMMAND_FORMAT" + DeleteDishCommand.MESSAGE_USAGE);
} catch (NumberFormatException nfe) {
Expand Down

0 comments on commit 2df1928

Please sign in to comment.