/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.php.internal.ui.editor.scanner.tokenMap;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java_cup.runtime.Symbol;
import org.eclipse.jface.text.rules.IToken;
import org2.eclipse.php.internal.core.PHPVersion;
import com.aptana.core.util.StringUtil;
import com.aptana.editor.php.internal.parser.PHPTokenType;
import com.aptana.editor.php.internal.ui.editor.scanner.PHPCodeScanner;
/**
* A PHP token mapper factory that returns the right {@link IPHPTokenMapper} according to the given {@link PHPVersion}.
*
* @author Shalom Gibly <sgibly@aptana.com>
* @author cwilliams
*/
@SuppressWarnings("nls")
public class PHPTokenMapperFactory
{
private static PHP4TokenMapper php4TokenMapper;
private static PHP5TokenMapper php5TokenMapper;
private static PHP53TokenMapper php53TokenMapper;
private static PHP54TokenMapper php54TokenMapper;
private static final Pattern CONSTANT_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_]*");
public static Set<String> GLOBALS = new HashSet<String>();
static
{
GLOBALS.add(IPHPTokenMapper.COOKIE);
GLOBALS.add(IPHPTokenMapper.FILES);
GLOBALS.add(IPHPTokenMapper.POST);
GLOBALS.add(IPHPTokenMapper.GET);
GLOBALS.add(IPHPTokenMapper.REQUEST);
GLOBALS.add(IPHPTokenMapper.PHP_SELF);
GLOBALS.add(IPHPTokenMapper.HTTP_POST_VARS);
GLOBALS.add(IPHPTokenMapper.HTTP_GET_VARS);
GLOBALS.add(IPHPTokenMapper.HTTP_ENV_VARS);
GLOBALS.add(IPHPTokenMapper.HTTP_SERVER_VARS);
GLOBALS.add(IPHPTokenMapper.HTTP_COOKIE_VARS);
}
public static Set<String> SAFER_GLOBALS = new HashSet<String>();
static
{
SAFER_GLOBALS.add(IPHPTokenMapper.GLOBALS);
SAFER_GLOBALS.add(IPHPTokenMapper.SESSION);
SAFER_GLOBALS.add(IPHPTokenMapper.SERVER);
SAFER_GLOBALS.add(IPHPTokenMapper.ENV);
}
private static Set<String> ASSIGNMENTS = new HashSet<String>();
static
{
ASSIGNMENTS.add("=");
ASSIGNMENTS.add("|=");
ASSIGNMENTS.add("&=");
ASSIGNMENTS.add("^=");
ASSIGNMENTS.add("%=");
ASSIGNMENTS.add("/=");
ASSIGNMENTS.add("*=");
}
private static Set<String> LOGICAL_OPERATORS = new HashSet<String>();
static
{
LOGICAL_OPERATORS.add("!");
LOGICAL_OPERATORS.add("&&");
LOGICAL_OPERATORS.add("||");
LOGICAL_OPERATORS.add("^");
LOGICAL_OPERATORS.add("and");
LOGICAL_OPERATORS.add("or");
LOGICAL_OPERATORS.add("xor");
LOGICAL_OPERATORS.add("as");
LOGICAL_OPERATORS.add("insteadof");
}
private static Set<String> INC_DEC_OPERATORS = new HashSet<String>();
static
{
INC_DEC_OPERATORS.add("--");
INC_DEC_OPERATORS.add("++");
}
private static Set<String> ARITHMETIC_OPERATORS = new HashSet<String>();
static
{
ARITHMETIC_OPERATORS.add("-");
ARITHMETIC_OPERATORS.add("+");
ARITHMETIC_OPERATORS.add("*");
ARITHMETIC_OPERATORS.add("/");
ARITHMETIC_OPERATORS.add("%");
}
private static Set<String> BITWISE_OPERATORS = new HashSet<String>();
static
{
BITWISE_OPERATORS.add("<<");
BITWISE_OPERATORS.add(">>");
BITWISE_OPERATORS.add("~");
BITWISE_OPERATORS.add("^");
BITWISE_OPERATORS.add("&");
BITWISE_OPERATORS.add("|");
}
private static Set<String> COMPARISON_OPERATORS = new HashSet<String>();
static
{
COMPARISON_OPERATORS.add("<");
COMPARISON_OPERATORS.add("==");
COMPARISON_OPERATORS.add("===");
COMPARISON_OPERATORS.add("!==");
COMPARISON_OPERATORS.add("!=");
COMPARISON_OPERATORS.add("<=");
COMPARISON_OPERATORS.add(">=");
COMPARISON_OPERATORS.add("<>");
COMPARISON_OPERATORS.add(">");
}
/**
* Returns the {@link IPHPTokenMapper} that match the given {@link PHPVersion}
*
* @param phpVersion
* @return An {@link IPHPTokenMapper}
* @throws IllegalArgumentException
* In case the PHP version is unknown.
*/
public static IPHPTokenMapper getMapper(PHPVersion phpVersion)
{
switch (phpVersion)
{
case PHP4:
if (php4TokenMapper == null)
{
php4TokenMapper = new PHP4TokenMapper();
}
return php4TokenMapper;
case PHP5:
if (php5TokenMapper == null)
{
php5TokenMapper = new PHP5TokenMapper();
}
return php5TokenMapper;
case PHP5_3:
if (php53TokenMapper == null)
{
php53TokenMapper = new PHP53TokenMapper();
}
return php53TokenMapper;
case PHP5_4:
if (php54TokenMapper == null)
{
php54TokenMapper = new PHP54TokenMapper();
}
return php54TokenMapper;
}
throw new IllegalArgumentException("Unknown PHP version " + phpVersion.getAlias()); //$NON-NLS-1$
}
/**
* Common handling of fall-through cases for scopes across versions of PHP token mappers.
*
* @param scanner
* @param sym
* @return
*/
public static IToken mapDefaultToken(PHPCodeScanner scanner, Symbol sym)
{
String tokenContent = scanner.getSymbolValue(sym);
if (";".equals(tokenContent))
{
return scanner.getToken(PHPTokenType.PUNCTUATION_TERMINATOR.toString());
}
if ("(".equals(tokenContent))
{
return scanner.getToken(PHPTokenType.PUNCTUATION_PARAM_LEFT.toString());
}
if (")".equals(tokenContent))
{
return scanner.getToken(PHPTokenType.PUNCTUATION_PARAM_RIGHT.toString());
}
if ("[".equals(tokenContent))
{
return scanner.getToken(PHPTokenType.PUNCTUATION_LBRACKET.toString());
}
if ("]".equals(tokenContent))
{
return scanner.getToken(PHPTokenType.PUNCTUATION_RBRACKET.toString());
}
// Operators
if (ASSIGNMENTS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_ASSIGN.toString());
}
if (LOGICAL_OPERATORS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_LOGICAL.toString());
}
if (COMPARISON_OPERATORS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_COMPARISON.toString());
}
if (ARITHMETIC_OPERATORS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_ARITHMETIC.toString());
}
if (BITWISE_OPERATORS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_BITWISE.toString());
}
if (INC_DEC_OPERATORS.contains(tokenContent))
{
return scanner.getToken(PHPTokenType.KEYWORD_OP_INC_DEC.toString());
}
// All uppercase is constant
if (CONSTANT_PATTERN.matcher(tokenContent).matches())
{
return scanner.getToken(PHPTokenType.CONSTANT_OTHER.toString());
}
return scanner.getToken(StringUtil.EMPTY);
}
}