blob: 5b151dc3f33ec610836ea345a0b9bf17a367086a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.ui.editors.xpath;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.bpel.ui.editors.xpath.rules.AxisRule;
import org.eclipse.bpel.ui.editors.xpath.rules.FloatRule;
import org.eclipse.bpel.ui.editors.xpath.rules.FunctionRule;
import org.eclipse.bpel.ui.editors.xpath.rules.ITokenContext;
import org.eclipse.bpel.ui.editors.xpath.rules.SingleCharRule;
import org.eclipse.bpel.ui.editors.xpath.rules.SingleOperatorRule;
import org.eclipse.bpel.ui.editors.xpath.rules.StringRule;
import org.eclipse.bpel.ui.editors.xpath.rules.WordRule;
import org.eclipse.bpel.ui.preferences.PreferenceConstants;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.IWordDetector;
import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WhitespaceRule;
import org.eclipse.swt.SWT;
/**
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date Oct 25, 2006
*/
public class XPathSourceScanner extends BufferedRuleBasedScanner {
IWordDetector fNCNameDetector = new XPathWordDetector.NCNameWordDetector ();
IWordDetector fWordDetector = new XPathWordDetector();
IWordDetector fVariableNameDetector = new XPathWordDetector.VariableDetector();
IWordDetector fQNameDetector = new XPathWordDetector.QNameDetector ();
LinkedList<IToken> tokenWindow = new LinkedList<IToken>();
/**
* The scanner for the XPath source editor, which provides
* syntax coloring based on the default damager and repairer.
*
* @param manager
*/
@SuppressWarnings("nls")
public XPathSourceScanner( ColorManager manager ) {
IToken defToken = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.DEFAULT )
) );
final IToken operatorToken = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.OPERAND ),
null,
SWT.BOLD
) );
IToken number = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.NUMBER ),
null,
SWT.BOLD
) );
IToken string = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.STRING ) ) ) ;
IToken brackets = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.BRACKET ),
null,
SWT.BOLD )
);
IToken axis = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.AXIS ),
null,
SWT.ITALIC )
);
IToken pathSep = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.PATH_SEPARATOR ),
null,
SWT.BOLD )
);
IToken functionsDefault = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.FUNCTIONS_XPATH ),
null,
SWT.ITALIC )
);
IToken functions = new Token (
new TextAttribute (
manager.getColor( PreferenceConstants.FUNCTIONS_XPATH ),
null,
SWT.BOLD)
) ;
final IToken variableToken = new Token (
new TextAttribute(
manager.getColor( PreferenceConstants.VARIABLES ),
null,
SWT.BOLD
));
IToken partToken = new Token (
new TextAttribute(
manager.getColor( PreferenceConstants.VARIABLE_PART ),
null,
SWT.BOLD
));
// The list of rules for this scanner.
List<IRule> rules = new ArrayList<IRule>(24);
// Add rule for double quotes string
rules.add( new SingleLineRule("\"", "\"", string , '\\') ); //$NON-NLS-1$ //$NON-NLS-2$
// Add a rule for single quotes string
rules.add( new SingleLineRule("'", "'", string , '\\') ); //$NON-NLS-1$ //$NON-NLS-2$
// Add function calls ...
// Add generic whitespace rule.
rules.add( new WhitespaceRule(new XPathWhitespaceDetector()) );
// numbers
rules.add ( new FloatRule ( number )) ;
WordRule wordRule;
// variable rule
wordRule = new WordRule ( fVariableNameDetector );
wordRule.addWord ( WordRule.ANY , variableToken );
rules.add (wordRule);
// Variable part rule
wordRule = new WordRule ( new XPathWordDetector.MessagePartDetector() );
wordRule.addWord ( WordRule.ANY , partToken );
wordRule.setTokenContextCheck( new TokenContext () {
@Override
public boolean checkSeenTokens(XPathSourceScanner scanner) {
return (scanner.lastToken(0) == variableToken);
}
});
rules.add (wordRule);
// Some operators.
rules.add ( new SingleOperatorRule ( operatorToken, "+-*=|/<>" ) );
// Operators of sorts ...
rules.add ( new StringRule ( operatorToken, "!=") );
rules.add ( new StringRule ( operatorToken, ">=") );
rules.add ( new StringRule ( operatorToken, "<=") );
rules.add ( new StringRule ( operatorToken, ">=") );
rules.add ( new SingleCharRule ( brackets, "[]().@," ) );
rules.add ( new StringRule ( operatorToken, "//") );
rules.add ( new StringRule ( pathSep, "::") );
// rule for operators ...
wordRule = new WordRule( new XPathWordDetector () );
wordRule.addWord ("mod",operatorToken);
wordRule.addWord ("div",operatorToken);
wordRule.addWord ("and",operatorToken);
wordRule.addWord ("or",operatorToken);
wordRule.setTokenContextCheck( new TokenContext() {
@Override
public boolean checkSeenTokens(XPathSourceScanner scanner) {
int idx = (scanner.lastToken(0) == Token.WHITESPACE ? 1 : 0);
return scanner.lastToken(idx) != operatorToken;
}
});
rules.add( wordRule );
AxisRule axisRule = new AxisRule ( fNCNameDetector );
axisRule.addWords(AXIS, axis);
rules.add(axisRule);
// The basic XPath functions
FunctionRule functionRule = new FunctionRule ( fQNameDetector );
functionRule.addWords(XPATH_FUNCTIONS,functionsDefault);
rules.add(functionRule);
// All other functions
functionRule = new FunctionRule ( fQNameDetector );
functionRule.addWord( WordRule.ANY,functions);
rules.add(functionRule);
wordRule = new WordRule( fWordDetector );
wordRule.addWord ( WordRule.ANY, defToken );
rules.add( wordRule );
setDefaultReturnToken( defToken ) ;
setRules ( rules.toArray(new IRule[]{} ));
}
/**
*
* @see org.eclipse.jface.text.rules.RuleBasedScanner#nextToken()
*/
@Override
public IToken nextToken() {
IToken next = super.nextToken();
tokenWindow.addFirst(next);
if (tokenWindow.size() > 4) {
tokenWindow.removeLast();
}
return next;
}
/**
* Returns the last token with the index of offset. Index 0 means the last token seen,
* 1 means the one before the last token seen.
*
* @param offset
* @return the token requested or undefined.
*/
public IToken lastToken ( int offset ) {
try {
return tokenWindow.get(offset);
} catch (Throwable t) {
return Token.UNDEFINED;
}
}
static private final String[] XPATH_FUNCTIONS = {
"last","position","count","id","local-name","namespace-uri","name",
"string","concat","starts-with","contains","substring-before","substring-after",
"substring","string-length","normalize-space","translate",
"boolean","not","true","false","lang",
"number","sum","floor","ceiling","round"
};
static private final String[] AXIS = {
"ancestor",
"ancestor-or-self",
"attribute",
"child",
"descendant",
"descendant-or-self",
"following",
"following-sibling",
"namespace",
"parent",
"preceding",
"preceding-sibling",
"self"
};
/**
* The TokenContext class allows us to see what tokens we have seen
* so far. In some syntax coloring constructs we need to have a memory
* (albeit a simple one) of where we have been.
*
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date Nov 27, 2006
*/
abstract class TokenContext implements ITokenContext {
/** (non-Javadoc)
* @see org.eclipse.bpel.ui.editors.xpath.rules.ITokenContext#check(org.eclipse.jface.text.rules.ICharacterScanner)
*/
public boolean check (ICharacterScanner scanner) {
if (scanner instanceof XPathSourceScanner) {
return checkSeenTokens ( (XPathSourceScanner) scanner);
}
return false;
}
/**
*
* @param scanner
* @return true if the right tokens have been seen so far, false
* otherwise.
*
*/
public abstract boolean checkSeenTokens ( XPathSourceScanner scanner ) ;
}
}