package com.quantum.editors; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.rules.EndOfLineRule; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IPredicateRule; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.IWhitespaceDetector; import org.eclipse.jface.text.rules.MultiLineRule; import org.eclipse.jface.text.rules.RuleBasedPartitionScanner; import org.eclipse.jface.text.rules.SingleLineRule; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.rules.WhitespaceRule; public class SQLPartitionScanner extends RuleBasedPartitionScanner { public final static String SQL_COMMENT = "__sql_comment"; //$NON-NLS-1$ public final static String SQL_IDENTIFIER = "__sql_word"; //$NON-NLS-1$ public final static String SQL_STRING = "__sql_string"; //$NON-NLS-1$ public final static String SQL_KEYWORD = "__sql_keyword"; //$NON-NLS-1$ public final static String SQL_SYMBOL = "__sql_symbol"; //$NON-NLS-1$ public final static String SQL_SEPARATOR = "__sql_separator"; //$NON-NLS-1$ public final static String SQL_NUMERIC = "__sql_numeric"; //$NON-NLS-1$ private final static String[] KEYWORDS = { "ALTER", //$NON-NLS-1$ "AND", //$NON-NLS-1$ "BY", //$NON-NLS-1$ "COLUMN", //$NON-NLS-1$ "CREATE", //$NON-NLS-1$ "DELETE", //$NON-NLS-1$ "DROP", //$NON-NLS-1$ "FROM", //$NON-NLS-1$ "GROUP", //$NON-NLS-1$ "INSERT", //$NON-NLS-1$ "INTO", //$NON-NLS-1$ "NOT", //$NON-NLS-1$ "NULL", //$NON-NLS-1$ "OR", //$NON-NLS-1$ "ORDER", //$NON-NLS-1$ "SELECT", //$NON-NLS-1$ "SEQUENCE", //$NON-NLS-1$ "SET", //$NON-NLS-1$ "TABLE", //$NON-NLS-1$ "UNION", //$NON-NLS-1$ "UNIQUE", //$NON-NLS-1$ "UPDATE", //$NON-NLS-1$ "USING", //$NON-NLS-1$ "VALUES", //$NON-NLS-1$ "VIEW", //$NON-NLS-1$ "WHEN", //$NON-NLS-1$ "WHERE" //$NON-NLS-1$ }; public SQLPartitionScanner() { List rules = new ArrayList(); IToken comment = new Token(SQL_COMMENT); IToken string = new Token(SQL_STRING); IToken identifier = new Token(SQL_IDENTIFIER); IToken keyword = new Token(SQL_KEYWORD); IToken separator = new Token(SQL_SEPARATOR); IToken symbol = new Token(SQL_SYMBOL); IToken whitespace = new Token(IDocument.DEFAULT_CONTENT_TYPE); IToken numeric = new Token(SQL_NUMERIC); rules.add(new PredicateRuleAdapter(new WhitespaceRule(new WhitespaceDetector()), whitespace)); rules.add(new MultiLineRule("/*", "*/", comment)); //$NON-NLS-1$ //$NON-NLS-2$ rules.add(new EndOfLineRule("--", comment)); //$NON-NLS-1$ rules.add(new SingleLineRule("'", "'", string)); //$NON-NLS-1$ //$NON-NLS-2$ rules.add(new PredicateRuleAdapter(new SQLNumberRule(numeric), numeric)); SQLWordRule wordRule = new SQLWordRule(identifier); for (int i = 0; i < KEYWORDS.length; i++) { wordRule.addKeyword(KEYWORDS[i], keyword); } rules.add(new PredicateRuleAdapter(wordRule, keyword)); rules.add(new PredicateRuleAdapter(wordRule, identifier)); rules.add(new PredicateRuleAdapter(new SQLSeparatorRule(separator), separator)); rules.add(new PredicateRuleAdapter(new SymbolRule(symbol), symbol)); IPredicateRule[] result= new IPredicateRule[rules.size()]; rules.toArray(result); setPredicateRules(result); } } class PredicateRuleAdapter implements IPredicateRule { IRule rule; IToken token; public PredicateRuleAdapter(IRule rule, IToken token) { this.rule = rule; this.token = token; } public IToken evaluate(ICharacterScanner scanner, boolean resume) { return rule.evaluate(scanner); } public IToken getSuccessToken() { return token; } public IToken evaluate(ICharacterScanner scanner) { return rule.evaluate(scanner); } } class SQLSeparatorRule implements IRule { IToken token; public SQLSeparatorRule(IToken token) { this.token = token; } public IToken evaluate(ICharacterScanner scanner) { char c = (char) scanner.read(); if (c == ';') { return token; } scanner.unread(); return Token.UNDEFINED; } } class SymbolRule implements IRule { IToken token; public SymbolRule(IToken token) { this.token = token; } public IToken evaluate(ICharacterScanner scanner) { int val = scanner.read(); if (val != ICharacterScanner.EOF) { char c = (char) val; if (!Character.isWhitespace(c) && !Character.isLetterOrDigit(c) && c != '_') { return token; } } scanner.unread(); return Token.UNDEFINED; } } class WhitespaceDetector implements IWhitespaceDetector { public boolean isWhitespace(char c) { return Character.isWhitespace(c); } } class SQLNumberRule implements IRule { private IToken token; public SQLNumberRule(IToken token) { this.token = token; } public IToken evaluate(ICharacterScanner scanner) { char c = (char) scanner.read(); if (Character.isDigit(c)) { // postive numbers and zero do { c= (char) scanner.read(); } while (Character.isDigit(c) || c == '.'); scanner.unread(); return token; } else if (c == '-') { // negative numbers c = (char) scanner.read(); if (Character.isDigit(c)) { do { c= (char) scanner.read(); } while (Character.isDigit(c) || c == '.'); scanner.unread(); return token; } else { scanner.unread(); scanner.unread(); return Token.UNDEFINED; } } else { scanner.unread(); return Token.UNDEFINED; } } } class SQLWordRule implements IRule { private IToken token; private HashMap keywords = new HashMap(); public SQLWordRule(IToken token) { this.token = token; } public void addKeyword(String word, IToken token) { keywords.put(word.toUpperCase(), token); } public IToken evaluate(ICharacterScanner scanner) { char c = (char) scanner.read(); if (Character.isLetter(c) || c == '_') { StringBuffer value = new StringBuffer(); do { value.append(c); c= (char) scanner.read(); } while (Character.isLetterOrDigit(c) || c == '_'); scanner.unread(); IToken retVal = (IToken) keywords.get(value.toString().toUpperCase()); if (retVal != null) { return retVal; } else { return token; } } else { scanner.unread(); return Token.UNDEFINED; } } }