See More

// Scan lexical tokens in input strings. package com.expr; import java.util.Vector; class Scanner { private String s; private String operatorChars; Vector tokens = new Vector<>(); int index = -1; public Scanner(String string, String operatorChars) { this.s = string; this.operatorChars = operatorChars; int i = 0; do { i = scanToken(i); } while (i < s.length()); } public String getInput() { return s; } // The tokens may have been diddled, so this can be different from // getInput(). public String toString() { StringBuffer sb = new StringBuffer(); int whitespace = 0; for (int i = 0; i < tokens.size(); ++i) { Token t = tokens.elementAt(i); int spaces = (whitespace != 0 ? whitespace : t.leadingWhitespace); if (i == 0) spaces = 0; else if (spaces == 0 && !joinable(tokens.elementAt(i - 1), t)) spaces = 1; for (int j = spaces; 0 < j; --j) sb.append(" "); sb.append(t.sval); whitespace = t.trailingWhitespace; } return sb.toString(); } private boolean joinable(Token s, Token t) { return !(isAlphanumeric(s) && isAlphanumeric(t)); } private boolean isAlphanumeric(Token t) { return t.ttype == Token.TT_WORD || t.ttype == Token.TT_NUMBER; } public boolean isEmpty() { return tokens.size() == 0; } public boolean atStart() { return index <= 0; } public boolean atEnd() { return tokens.size() <= index; } public Token nextToken() { ++index; return getCurrentToken(); } public Token getCurrentToken() { if (atEnd()) return new Token(Token.TT_EOF, 0, s, s.length(), s.length()); return (Token) tokens.elementAt(index); } private int scanToken(int i) { while (i < s.length() && Character.isWhitespace(s.charAt(i))) ++i; if (i == s.length()) { return i; } else if (0 <= operatorChars.indexOf(s.charAt(i))) { if (i + 1 < s.length()) { String pair = s.substring(i, i + 2); int ttype = 0; switch (pair) { case "<=": ttype = Token.TT_LE; break; case ">=": ttype = Token.TT_GE; break; case "<>": ttype = Token.TT_NE; break; } if (0 != ttype) { tokens.addElement(new Token(ttype, 0, s, i, i + 2)); return i + 2; } } tokens.addElement(new Token(s.charAt(i), 0, s, i, i + 1)); return i + 1; } else if (Character.isLetter(s.charAt(i))) { return scanSymbol(i); } else if (Character.isDigit(s.charAt(i)) || '.' == s.charAt(i)) { return scanNumber(i); } else { tokens.addElement(makeErrorToken(i, i + 1)); return i + 1; } } private int scanSymbol(int i) { int from = i; while (i < s.length() && (Character.isLetter(s.charAt(i)) || Character.isDigit(s.charAt(i)))) ++i; tokens.addElement(new Token(Token.TT_WORD, 0, s, from, i)); return i; } private int scanNumber(int i) { int from = i; // We include letters in our purview because otherwise we'd // accept a word following with no intervening space. for (; i < s.length(); ++i) if ('.' != s.charAt(i) && !Character.isDigit(s.charAt(i)) && !Character.isLetter(s.charAt(i))) break; String text = s.substring(from, i); double nval; try { nval = Double.valueOf(text); } catch (NumberFormatException nfe) { tokens.addElement(makeErrorToken(from, i)); return i; } tokens.addElement(new Token(Token.TT_NUMBER, nval, s, from, i)); return i; } private Token makeErrorToken(int from, int i) { return new Token(Token.TT_ERROR, 0, s, from, i); } }