package function; import java.text.MessageFormat; import error.LispException; import function.builtin.LENGTH; import sexpression.*; public class ArgumentValidator { private Class argumentType; private String functionName; private Integer maximumNumberOfArguments; private Integer minimumNumberOfArguments; public ArgumentValidator(String functionName) { this.argumentType = SExpression.class; this.functionName = functionName; this.minimumNumberOfArguments = null; this.maximumNumberOfArguments = null; } public void setArgumentType(Class argumentType) { this.argumentType = argumentType; } public void setMaximumNumberOfArguments(int maximumNumberOfArguments) { this.maximumNumberOfArguments = maximumNumberOfArguments; } public void setMinimumNumberOfArguments(int minimumNumberOfArguments) { this.minimumNumberOfArguments = minimumNumberOfArguments; } public void setExactNumberOfArguments(int exactNumberOfArguments) { this.minimumNumberOfArguments = exactNumberOfArguments; this.maximumNumberOfArguments = exactNumberOfArguments; } public void validate(Cons argumentList) { if (containsTooFewArguments(argumentList)) throw new TooFewArgumentsException(functionName, argumentList); else if (containsTooManyArguments(argumentList)) throw new TooManyArgumentsException(functionName, argumentList); else if (!isExpectedArgumentType(argumentList.getCar())) throw new BadArgumentTypeException(functionName, argumentList.getCar()); } private boolean containsTooFewArguments(Cons argumentList) { return (minimumNumberOfArguments != null) && (LENGTH.getLength(argumentList) < minimumNumberOfArguments); } private boolean containsTooManyArguments(Cons argumentList) { return (maximumNumberOfArguments != null) && (LENGTH.getLength(argumentList) > maximumNumberOfArguments); } private boolean isExpectedArgumentType(SExpression firstArgument) { return argumentType.isInstance(firstArgument); } public static class TooFewArgumentsException extends LispException { private static final long serialVersionUID = 1L; private String functionName; private Cons originalSExpression; public TooFewArgumentsException(String functionName, Cons argumentList) { this.functionName = functionName; this.originalSExpression = new Cons(new Symbol(this.functionName), argumentList); } @Override public String getMessage() { return MessageFormat.format("too few arguments given to {0}: {1}", functionName, originalSExpression); } } public static class TooManyArgumentsException extends LispException { private static final long serialVersionUID = 1L; private String functionName; private Cons originalSExpression; public TooManyArgumentsException(String functionName, Cons argumentList) { this.functionName = functionName; this.originalSExpression = new Cons(new Symbol(this.functionName), argumentList); } @Override public String getMessage() { return MessageFormat.format("too many arguments given to {0}: {1}", functionName, originalSExpression); } } public static class BadArgumentTypeException extends LispException { private static final long serialVersionUID = 1L; private String functionName; private String argument; public BadArgumentTypeException(String functionName, SExpression argument) { this.functionName = functionName; this.argument = argument.toString(); } @Override public String getMessage() { return MessageFormat.format("{0}: {1} is not the expected type", functionName, argument); } } }