<commit_before>package configuration;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import application.CommandFactory;
import commands.*;
public class Parser {
	private HashMap<String, String> commandMap;
	private HashSet<String> userdefined;
	private HashMap<String, String> lanMap;
	private final String onenum = "\\s(\\d+)"; //one parameter only exactly one space between parameters
	private final String twonum = "\\s(\\d+)\\s(\\d+)";	//two parameter
	private final String com_regix = "\\s\\[(.*?)\\]"; //[command]
	private final String variable = "\\s(:\\w+)";
	private final String constant = "-?\\d+.?\\d*";
	private final String commandname = "\\w+[?]?";	
	private final String boolean_regix = "\\s(less\\?\\s\\d+\\s\\d+|greater\\?\\s\\d+\\s\\d+|equal\\?\\s\\d+\\s\\d+)";

	private final String[] commands = new String[]{"fd", "forward", "backward", "bk", "settowards", "tw", "setxy", "sum", "+", "difference","-", "product","*",
			"quotient","remainder", "%", "/","#","left", "lt", "right", "rt", "setheading", "seth", "sine", "cosine", "tangent", "arctangent", "repeat", "dotimes","for",
			"if","ifelse", "makeuserinstruction", "make", "set","less?", "greater?", "equal?"};
	
	private final String[] regix = new String[]{ onenum, onenum, onenum,  onenum, twonum,  twonum, twonum, twonum, twonum,  twonum,  twonum, twonum,
			twonum, twonum, twonum,  twonum, twonum, ".*",onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum +com_regix, 
			 "\\s\\["+variable+onenum+"\\s\\]"+com_regix, "\\s\\[" + variable + twonum + onenum + "\\s\\]" + com_regix, boolean_regix + com_regix, 
			 boolean_regix  + com_regix + com_regix, "\\s" + commandname + "\\s\\[" + variable + "\\s\\]" + com_regix, variable + "\\s.*", variable + "\\s.*",
			 twonum,  twonum, twonum};

/*			if(regex.equals(onenum)){				
				//set parameters CommandFactory.execute(String.valueOf(group(1)));
			}			
			else if(regex.equals(twonum)){	
				//set two parameters and execute CommandFatory.execute(String.valueOf(group(1)), String.valueOf(group(2)))
			}	
*/			

public void parse(String in){		
	CommandFactory com =  parseInput(in);
	if(com  != null)	com.execute();
}
	
private CommandFactory parseInput(String in) {
		String temp = in.trim().toLowerCase();//sanitized input 
		String[] comArray = temp.split(" ");
		String comKey = comArray[0];
		String com = lanMap.get(comKey);
		String commandRegex = commandMap.get(com);
		String s = temp.replaceFirst(com, "");		
		if(userdefined.contains(com)){
			return parseLoopCommands(s, commandRegex, com);	
		}
		else{
			return parseBasicCommand(s, commandRegex, com); //parse babsic command
		}		
	}
	private CommandFactory parseLoopCommands(String in, String regex, String com){
		int var = Integer.MAX_VALUE;
		ArrayList<CommandFactory> list = new ArrayList();
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(in);	
		System.out.println("Loop command is "+ com);
		switch(com){
			case "if":{	
				while(m.find()){
					int expr = parseInput(m.group(1)).execute(); //boolean expression
					System.out.println("Booean is evaluted to " + expr);
					if(expr == 1){ //no object created when expr is evaluated to 0
					for(int i = 2; i <= m.groupCount(); i++){
						list.add(parseInput(m.group(i)));
					}		
					return new IfCond(expr, list);	
					}
				} 
			}
			case "repeat":{
				while(m.find()){
					for(int i = 2; i <= m.groupCount(); i++){
						list.add(parseInput(m.group(i)));
					}
					System.out.println("iteration times = " +Integer.parseInt(m.group(1)));
					return new Repeat(Integer.parseInt(m.group(1)), list);
				}
			}
			case "dotimes":{
				while(m.find()){
					for(int i = 3; i <= m.groupCount(); i++){  
						list.add(parseInput(m.group(i).replaceAll(""+m.group(1), " "+ var))); //replace variable with 
					}
				System.out.println("variable is " + m.group(1));	
				System.out.println("limit = " + Integer.parseInt(m.group(2)));	
				return new DoTimes(Integer.parseInt(m.group(2)), list);
				}
			}
			case "ifelse":{
				int expr = 0;
				while(m.find()){
				 expr = parseInput(m.group(1)).execute(); //boolean expression
				 System.out.println("expression evaluation = " + expr);
					if(expr == 1)
						for(int i = 2; i <= m.groupCount(); i++){ //m.group(2) is if and m.group(3) is elses 
							list.add(parseInput(m.group(i)));
						}
					else if(expr == 0)
						for(int i = 3; i <= m.groupCount(); i++){
							list.add(parseInput(m.group(i)));
						}
				}
				return new IfCond(expr, list);
			}
			case "for":{ //first 3 is int
				while(m.find()){
					for(int i = 5; i <= m.groupCount(); i++){  
						list.add(parseInput(m.group(i).replaceAll(m.group(1), " "+ var))); //replace variable with 
					}
					int start = Integer.parseInt(m.group(2));
					int end = Integer.parseInt(m.group(3));
					int inc = Integer.parseInt(m.group(4));
					System.out.println("variable = " + m.group(1)+ "    "+ "start, end, inc is "+ start+ " " + " "+ end+ " "+ inc+ " respectively");
					return new For(start, end, inc, list);
				}
			}

	}
		return null;
	}
	private CommandFactory parseBasicCommand(String in, String commandRegex, String com){	
		if(com.equals("home"))	return new Home();
		Pattern p = Pattern.compile(commandRegex);
		Matcher m = p.matcher(in);				
		int[] par = new int[2];
		while(m.find()){
			for(int i = 1; i <= m.groupCount(); i++){
				par[i - 1]= Integer.parseInt(m.group(i));	
			}
			return executeBasic(com, par);
		}
			System.out.println("Basic Command is " + com);
			System.out.println("Command "+com+" parameters is " + par[0] + " "+ par[1]);
			
		return null;
	}
	

	private CommandFactory executeBasic(String com, int[] par){
	switch(com){
		case "forward": 	return new Forward(par[0]);
		case "back":		return new Backward(par[0]);
		case "towards":		return new GoTowardsLoc(5, 4);
		case "setxy":		return new GoToLocation(par[0], par[1]);
		case "sum":			return new Add(par[0], par[1]);
		case "difference":	return new Subtract(par[0], par[1]);
		case "product":		return new Multiply(par[0], par[1]);
		case "quotient":	return new Divide(par[0] , par[1]);
		case "remainder":	return new Remainder(par[0], par[1]);
		//case "#":			
		case "left":		return new Left(par[0]);
		case "right":		return new Right(par[0]);
		case "setheading":	return new SetHeading(par[0]);
		case "sin":			return new Sin(par[0]);
		case "cos":			return new Cos(par[0]);
		case "tan":			return new Tan(par[0]);
		case "atan":		return new ATan(par[0]);
		case "less?":		return new Less(par[0], par[1]);
		case "greater?":	return new Greater(par[0], par[1]);
		case "equal?":		return new Equal(par[0], par[1]);		
		}
		return null;	
	}
	
	public void setLanguage(ResourceBundle r){
		lanMap  = new HashMap<>();
		HashSet<String> m = (HashSet<String>) r.keySet();	
		for( String key: m){
			String value = r.getString(key);
			String[] val = value.split("\\|");
	  		//System.out.println(val[0]);
			for(int i=0; i< val.length; i++){
				lanMap.put(val[i].toLowerCase(), key.toLowerCase());
			}
		}

/*		Enumeration<String> m =  r.getKeys();
		System.out.println(m);	
		if(m.hasMoreElements()){
			String key = m.nextElement();
			String value = r.getString(key);
			String[] val = value.split("|");
			for(int i=0; i< val.length; i++){
				lanMap.put(val[i].toLowerCase(), key.toLowerCase());<commit_msg>bug fixed<commit_after>package configuration;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import application.CommandFactory;
import commands.*;
public class Parser {
	private HashMap<String, String> commandMap;
	private HashSet<String> userdefined;
	private HashMap<String, String> lanMap;
	private final String onenum = "\\s(\\d+)"; //one parameter only exactly one space between parameters
	private final String twonum = "\\s(\\d+)\\s(\\d+)";	//two parameter
	private final String com_regix = "\\s\\[(.*?)\\]"; //[command]
	private final String variable = "\\s(:\\w+)";
	private final String constant = "-?\\d+.?\\d*";
	private final String commandname = "\\w+[?]?";	
	private final String boolean_regix = "\\s(less\\?\\s\\d+\\s\\d+|greater\\?\\s\\d+\\s\\d+|equal\\?\\s\\d+\\s\\d+)";

	private final String[] commands = new String[]{"fd", "forward", "backward", "bk", "settowards", "tw", "setxy", "sum", "+", "difference","-", "product","*",
			"quotient","remainder", "%", "/","#","left", "lt", "right", "rt", "setheading", "seth", "sine", "cosine", "tangent", "arctangent", "repeat", "dotimes","for",
			"if","ifelse", "makeuserinstruction", "make", "set","less?", "greater?", "equal?"};
	
	private final String[] regix = new String[]{ onenum, onenum, onenum,  onenum, twonum,  twonum, twonum, twonum, twonum,  twonum,  twonum, twonum,
			twonum, twonum, twonum,  twonum, twonum, ".*",onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum, onenum +com_regix, 
			 "\\s\\["+variable+onenum+"\\s\\]"+com_regix, "\\s\\[" + variable + twonum + onenum + "\\s\\]" + com_regix, boolean_regix + com_regix, 
			 boolean_regix  + com_regix + com_regix, "\\s" + commandname + "\\s\\[" + variable + "\\s\\]" + com_regix, variable + "\\s.*", variable + "\\s.*",
			 twonum,  twonum, twonum};

/*			if(regex.equals(onenum)){				
				//set parameters CommandFactory.execute(String.valueOf(group(1)));
			}			
			else if(regex.equals(twonum)){	
				//set two parameters and execute CommandFatory.execute(String.valueOf(group(1)), String.valueOf(group(2)))
			}	
*/			

public void parse(String in){		
	CommandFactory com =  parseInput(in);
	if(com  != null)	com.execute();
}
	
private CommandFactory parseInput(String in) {
		String temp = in.trim().toLowerCase();//sanitized input 
		String[] comArray = temp.split(" ");
		String comKey = comArray[0];
		String com = lanMap.get(comKey);
		String commandRegex = commandMap.get(com);
		String s = temp.replaceFirst(com, "");		
		if(userdefined.contains(com)){
			return parseLoopCommands(s, commandRegex, com);	
		}
		else{
			return parseBasicCommand(s, commandRegex, com); //parse babsic command
		}		
	}
	private CommandFactory parseLoopCommands(String in, String regex, String com){
		int var = Integer.MAX_VALUE;
		ArrayList<CommandFactory> list = new ArrayList();
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(in);	
		System.out.println("Loop command is "+ com);
		switch(com){
			case "if":{	
				while(m.find()){
					int expr = parseInput(m.group(1)).execute(); //boolean expression
					System.out.println("Booean is evaluted to " + expr);
					if(expr == 1){ //no object created when expr is evaluated to 0
					for(int i = 2; i <= m.groupCount(); i++){
						list.add(parseInput(m.group(i)));
					}		
					return new IfCond(expr, list);	
					}
				} 
			}
			case "repeat":{
				while(m.find()){
					for(int i = 2; i <= m.groupCount(); i++){
						list.add(parseInput(m.group(i)));
					}
					System.out.println("iteration times = " +Integer.parseInt(m.group(1)));
					return new Repeat(Integer.parseInt(m.group(1)), list);
				}
			}
			case "dotimes":{
				while(m.find()){
					for(int i = 3; i <= m.groupCount(); i++){  
						list.add(parseInput(m.group(i).replaceAll(""+m.group(1), " "+ var))); //replace variable with 
					}
				System.out.println("variable is " + m.group(1));	
				System.out.println("limit = " + Integer.parseInt(m.group(2)));	
				return new DoTimes(Integer.parseInt(m.group(2)), list);
				}
			}
			case "ifelse":{
				int expr = 0;
				while(m.find()){
				 expr = parseInput(m.group(1)).execute(); //boolean expression
				 System.out.println("expression evaluation = " + expr);
					if(expr == 1)
						for(int i = 2; i <= m.groupCount(); i++){ //m.group(2) is if and m.group(3) is elses 
							list.add(parseInput(m.group(i)));
						}
					else if(expr == 0)
						for(int i = 3; i <= m.groupCount(); i++){
							list.add(parseInput(m.group(i)));
						}
				}
				return new IfCond(expr, list);
			}
			case "for":{ //first 3 is int
				while(m.find()){
					for(int i = 5; i <= m.groupCount(); i++){  
						list.add(parseInput(m.group(i).replaceAll(m.group(1), " "+ var))); //replace variable with 
					}
					int start = Integer.parseInt(m.group(2));
					int end = Integer.parseInt(m.group(3));
					int inc = Integer.parseInt(m.group(4));
					System.out.println("variable = " + m.group(1)+ "    "+ "start, end, inc is "+ start+ " " + " "+ end+ " "+ inc+ " respectively");
					return new For(start, end, inc, list);
				}
			}

	}
		return null;
	}
	private CommandFactory parseBasicCommand(String in, String commandRegex, String com){	
		if(com.equals("home"))	return new Home();
		Pattern p = Pattern.compile(commandRegex);
		Matcher m = p.matcher(in);				
		int[] par = new int[2];
		while(m.find()){
			for(int i = 1; i <= m.groupCount(); i++){
				par[i - 1]= Integer.parseInt(m.group(i));	
			}
			return executeBasic(com, par);
		}
			System.out.println("Basic Command is " + com);
			System.out.println("Command "+com+" parameters is " + par[0] + " "+ par[1]);
			
		return null;
	}
	

	private CommandFactory executeBasic(String com, int[] par){
	switch(com){
		case "forward": 	return new Forward(par[0]);
		case "backward":		return new Backward(par[0]);
		case "settowards":		return new GoTowardsLoc(5, 4);
		case "setxy":		return new GoToLocation(par[0], par[1]);
		case "sum":			return new Add(par[0], par[1]);
		case "difference":	return new Subtract(par[0], par[1]);
		case "product":		return new Multiply(par[0], par[1]);
		case "quotient":	return new Divide(par[0] , par[1]);
		case "remainder":	return new Remainder(par[0], par[1]);
		//case "#":			
		case "left":		return new Left(par[0]);
		case "right":		return new Right(par[0]);
		case "setheading":	return new SetHeading(par[0]);
		case "sine":			return new Sin(par[0]);
		case "cosine":			return new Cos(par[0]);
		case "tangent":			return new Tan(par[0]);
		case "arctangent":		return new ATan(par[0]);
		case "less?":		return new Less(par[0], par[1]);
		case "greater?":	return new Greater(par[0], par[1]);
		case "equal?":		return new Equal(par[0], par[1]);		
		}
		return null;	
	}

	public void setLanguage(ResourceBundle r){
		lanMap  = new HashMap<>();
		HashSet<String> m = (HashSet<String>) r.keySet();	
		for( String key: m){
			String value = r.getString(key);
			String[] val = value.split("\\|");
	  		//System.out.println(val[0]);
			for(int i=0; i< val.length; i++){
				lanMap.put(val[i].toLowerCase(), key.toLowerCase());
			}
		}

/*		Enumeration<String> m =  r.getKeys();
		System.out.println(m);	
		if(m.hasMoreElements()){
			String key = m.nextElement();
			String value = r.getString(key);
			String[] val = value.split("|");
			for(int i=0; i< val.length; i++){
				lanMap.put(val[i].toLowerCase(), key.toLowerCase());
{'fraction_non_alphanumeric': 0.1976728453524557, 'fraction_numerical': 0.00920037883912867, 'mean_word_length': 3.500152207001522, 'pattern_counts': {'":': 50, '<': 37, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5154584', 'n_tokens_mistral': 6034, 'n_tokens_neox': 5228, 'n_words': 1252}