package com.github.sommeri.less4j.core.compiler.expressions;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.github.sommeri.less4j.core.ast.ASTCssNodeType;
import com.github.sommeri.less4j.core.ast.Expression;
import com.github.sommeri.less4j.core.ast.FunctionExpression;
import com.github.sommeri.less4j.core.ast.IdentifierExpression;
import com.github.sommeri.less4j.core.ast.NumberExpression;
import com.github.sommeri.less4j.core.ast.NumberExpression.Dimension;
import com.github.sommeri.less4j.core.parser.HiddenTokenAwareTree;
import com.github.sommeri.less4j.core.problems.ProblemsHandler;
public class TypeFunctions extends BuiltInFunctionsPack {
protected static final String ISCOLOR = "iscolor";
protected static final String IS_RULESET = "isruleset";
protected static final String ISKEYWORD = "iskeyword";
protected static final String ISNUMBER = "isnumber";
protected static final String ISSTRING = "isstring";
protected static final String ISPIXEL = "ispixel";
protected static final String ISPERCENTAGE = "ispercentage";
protected static final String ISEM = "isem";
protected static final String ISURL = "isurl";
protected static final String ISUNIT = "isunit";
protected static final String ISLIST = "islist";
private static Map<String, Function> FUNCTIONS = new HashMap<String, Function>();
static {
FUNCTIONS.put(ISCOLOR, new IsColor());
FUNCTIONS.put(IS_RULESET, new IsRuleset());
FUNCTIONS.put(ISKEYWORD, new IsKeyword());
FUNCTIONS.put(ISNUMBER, new IsNumber());
FUNCTIONS.put(ISSTRING, new IsString());
FUNCTIONS.put(ISPIXEL, new IsPixel());
FUNCTIONS.put(ISPERCENTAGE, new IsPercentage());
FUNCTIONS.put(ISEM, new IsEm());
FUNCTIONS.put(ISURL, new IsUrl());
FUNCTIONS.put(ISUNIT, new IsUnit());
FUNCTIONS.put(ISLIST, new IsList());
}
public TypeFunctions(ProblemsHandler problemsHandler) {
super(problemsHandler);
}
@Override
protected Map<String, Function> getFunctions() {
return FUNCTIONS;
}
}
class IsColor extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.COLOR_EXPRESSION;
}
}
class IsRuleset extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.DETACHED_RULESET;
}
}
class IsList extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.LIST_EXPRESSION;
}
}
class IsKeyword extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.IDENTIFIER_EXPRESSION;
}
}
class IsNumber extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.NUMBER;
}
}
class IsString extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.STRING_EXPRESSION;
}
}
class IsUrl extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
if (parameter.getType() != ASTCssNodeType.FUNCTION)
return false;
FunctionExpression function = (FunctionExpression) parameter;
return function.getName().equalsIgnoreCase("url");
}
}
class IsPixel extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.NUMBER && ((NumberExpression)parameter).getSuffix().equalsIgnoreCase("px");
}
}
class IsUnit extends CatchAllMultiParameterFunction {
private final TypesConversionUtils utils = new TypesConversionUtils();
@Override
protected Expression evaluate(List<Expression> splitParameters, ProblemsHandler problemsHandler, FunctionExpression functionCall, HiddenTokenAwareTree token) {
Expression expression = splitParameters.get(0);
Expression unitExpression = splitParameters.get(1);
String unit = utils.contentToString(unitExpression);
if (expression.getType()!=ASTCssNodeType.NUMBER || unit==null)
return new IdentifierExpression(functionCall.getUnderlyingStructure(), "false");
return isunit((NumberExpression) expression, unit, functionCall.getUnderlyingStructure());
}
private Expression isunit(NumberExpression expression, String unit, HiddenTokenAwareTree token) {
String suffix = expression.getSuffix();
String result="true";
if (suffix == null || unit.isEmpty() || !suffix.equals(unit))
result="false";
return new IdentifierExpression(token, result);
}
@Override
protected boolean validateParameter(Expression parameter, int position, ProblemsHandler problemsHandler) {
return true;
}
@Override
protected int getMinParameters() {
return 2;
}
@Override
protected int getMaxParameters() {
return 2;
}
@Override
protected String getName() {
return TypeFunctions.ISUNIT;
}
}
class IsPercentage extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.NUMBER && ((NumberExpression)parameter).getDimension() == Dimension.PERCENTAGE;
}
}
class IsEm extends AbstractTypeFunction {
@Override
protected boolean checkType(Expression parameter) {
return parameter.getType() == ASTCssNodeType.NUMBER && ((NumberExpression)parameter).getSuffix().equalsIgnoreCase("em");
}
}
abstract class AbstractTypeFunction extends AbstractFunction {
@Override
public Expression evaluate(List<Expression> parameters, ProblemsHandler problemsHandler, FunctionExpression call, Expression evaluatedParameter) {
if (parameters.size()>1)
problemsHandler.wrongNumberOfArgumentsToFunctionMin(call.getParameter(), call.getName(), 1);
Expression parameter = parameters.get(0);
if (checkType(parameter)) {
return new IdentifierExpression(parameter.getUnderlyingStructure(), "true");
} else {
return new IdentifierExpression(parameter.getUnderlyingStructure(), "false");
}
}
protected abstract boolean checkType(Expression parameter);
}