package mulCal.equationParser; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /* * '-' is a bitch; * it can be part of a number "-4", * an operator "10 - 3", * or a unary function "-(5+2)". */ public class Tokenize { public static enum TokenType { NUMBER, FUNCTION, OPERATOR, VARIABLE, SPECIAL, OPENBRACKET, CLOSEBRACKET } private static String asciiUpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static class Token { public TokenType type; public String text; public Token(TokenType type, String text){ this.type = type; this.text = text; } } public static String asString(List<Token> tokens) { String result = ""; for (Token token : tokens) { result += token.text + " "; } return result; } public static List<Token> toTokens(String input) throws Exception { List<Token> tokens = new LinkedList<Token>(); input = input.trim(); while (input.length() != 0) { Token token; if (input.charAt(0) == '[') { token = new Token(TokenType.SPECIAL, readSpecial(input)); } else if ('(' == input.charAt(0)) { token = new Token(TokenType.OPENBRACKET, "("); } else if (')' == input.charAt(0)) { token = new Token(TokenType.CLOSEBRACKET, ")"); } else if (startWithNumber(input)) { token = new Token(TokenType.NUMBER, readNumber(input)); } else if (asciiUpperCase.contains(Character.toString(input.charAt(0)))) { token = new Token(TokenType.VARIABLE, readVariable(input)); } else { if (tokens.isEmpty() || nextIsFunction(tokens.get(tokens.size() - 1))) { token = new Token(TokenType.FUNCTION, readFunction(input)); } else { token = new Token(TokenType.OPERATOR, readFunction(input)); } } tokens.add(token); input = input.substring(token.text.length()); input = input.trim(); } return tokens; } public static boolean nextIsFunction(Token lastToken) { if (lastToken.type == TokenType.OPENBRACKET || lastToken.type == TokenType.OPERATOR || lastToken.type == TokenType.FUNCTION) { return true; } else { return false; } } public static boolean startWithNumber(String input) { // TODO add scientific notation Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?"); Matcher matcher = pattern.matcher(input); return matcher.lookingAt(); } public static String readFunction(String input) throws Exception { try { Pattern pattern = Pattern.compile("[a-z]+|[!%*/+]|\\^|\\-"); Matcher matcher = pattern.matcher(input); matcher.lookingAt(); return matcher.group(); } catch (IllegalStateException e) { throw new Exception("Tokenize.readFunction: cannot understand equation " + input); } } public static String readVariable(String input) { Pattern pattern = Pattern.compile("[A-Z]*"); Matcher matcher = pattern.matcher(input); matcher.lookingAt(); return matcher.group(); } public static String readNumber(String input) { // TODO add scientific notation Pattern pattern = Pattern.compile("-?\\d+(\\.\\d+)?"); Matcher matcher = pattern.matcher(input); matcher.lookingAt(); return matcher.group(); } public static String readSpecial(String input) { Pattern pattern = Pattern.compile("\\[[^\\]]*\\]"); Matcher matcher = pattern.matcher(input); matcher.lookingAt(); return matcher.group(); } }