Mercurial Hosting > nabble
view src/nabble/naml/compiler/CommandSpec.java @ 62:4674ed7d56df default tip
remove n2
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 30 Sep 2023 20:25:29 -0600 |
parents | 7ecd1a4ef557 |
children |
line wrap: on
line source
package nabble.naml.compiler; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public final class CommandSpec { public static CommandSpec.Builder DO() { return new CommandSpec.Builder() .scopedParameters("do") .dotParameter("do") .outputtedParameters("do") .optionalParameters("do") ; } public static final CommandSpec DO = DO().build(); public static CommandSpec.Builder TEXT() { return new CommandSpec.Builder() .dotParameter("text") ; } public static final CommandSpec TEXT = TEXT().build(); public static final CommandSpec OPTIONAL_TEXT = TEXT() .optionalParameters("text") .build() ; public final static CommandSpec EMPTY = new Builder().build(); public static CommandSpec.Builder NO_OUTPUT() { return new CommandSpec.Builder() .outputtedParameters() ; } public static final CommandSpec NO_OUTPUT = NO_OUTPUT().build(); final Set<String> parameters; final Set<String> scopedParameters; final String dotParameter; final Set<String> requiredParameters; private final Map<String,Set<String>> restrictedParams; final boolean removeNulls; final Set<String> outputtedParameters; final Set<Class> requiredInStack; public static class Builder { private final Set<String> parameters = new HashSet<String>(); private Set<String> scopedParameters = null; private String dotParameter = null; private Set<String> optionalParameters = null; private Map<String,Set<String>> restrictedParams = null; private boolean removeNulls = true; private Set<String> outputtedParameters = null; private final Set<Class> requiredInStack = new HashSet<Class>(); public Builder parameters(String... parameters) { this.parameters.addAll( Arrays.asList(parameters) ); return this; } public Builder scopedParameters(String... params) { this.scopedParameters = new HashSet<String>( Arrays.asList(params) ); return this; } public Builder dotParameter(String param) { this.dotParameter = param; return this; } public Builder optionalParameters(String... params) { if( optionalParameters == null ) optionalParameters = new HashSet<String>(); optionalParameters.addAll( Arrays.asList(params) ); return this; } public Builder restrictedParameter(String param,String... options) { if( restrictedParams==null ) restrictedParams = new HashMap<String,Set<String>>(); restrictedParams.put( param, new HashSet<String>(Arrays.asList(options)) ); return this; } public Builder dontRemoveNulls() { removeNulls = false; return this; } public Builder outputtedParameters(String... params) { if( outputtedParameters == null ) outputtedParameters = new HashSet<String>(); outputtedParameters.addAll( Arrays.asList(params) ); return this; } public Builder requiredInStack(Class... requiredInStack) { this.requiredInStack.addAll( Arrays.asList(requiredInStack) ); return this; } public CommandSpec build() { return new CommandSpec(this); } } private CommandSpec(Builder builder) { parameters = builder.parameters; scopedParameters = builder.scopedParameters; dotParameter = builder.dotParameter; restrictedParams = builder.restrictedParams; outputtedParameters = builder.outputtedParameters; requiredInStack = builder.requiredInStack.isEmpty() ? Collections.<Class>emptySet() : builder.requiredInStack; if( scopedParameters != null ) parameters.addAll(scopedParameters); if( dotParameter != null ) parameters.add(dotParameter); if( restrictedParams != null ) parameters.addAll(restrictedParams.keySet()); if( outputtedParameters != null ) parameters.addAll(outputtedParameters); requiredParameters = new HashSet<String>(parameters); if( builder.optionalParameters != null ) { parameters.addAll(builder.optionalParameters); requiredParameters.removeAll(builder.optionalParameters); } removeNulls = builder.removeNulls; for( String s : parameters ) { if( s.indexOf('-') != -1 ) throw new RuntimeException("macro attibute '"+s+"' may not contain '-'"); } } boolean hasScopedParam(String param) { return scopedParameters!=null && scopedParameters.contains(param); } Set<String> getParameters() { return Collections.unmodifiableSet(parameters); } boolean hasParameter(String param) { return parameters.contains(param); } static final String dotWarning = "you may have forgotten the dot at the end of the enclosing tag name"; void check(Map<String,String> staticArgs,Map<String,Chunk> dynamicArgs,StackTrace stackTrace) throws CompileException { Set<String> params = new HashSet<String>(); params.addAll(staticArgs.keySet()); params.addAll(dynamicArgs.keySet()); if( !parameters.containsAll(params) ) { params.removeAll(parameters); String msg = "parameter(s) "+params+" not allowed, only use "+parameters; if( dotParameter != null ) msg += " or "+dotWarning; throw new CompileException(stackTrace,msg); } if( !params.containsAll(requiredParameters) ) { Set<String> required = new HashSet<String>(requiredParameters); required.removeAll(params); if( required.size()==1 && required.iterator().next().equals(dotParameter) ) throw new CompileMethodException(stackTrace,"dot_parameter "+required+" was not found but is required, "+dotWarning); throw new CompileMethodException(stackTrace,"parameter(s) "+required+" were not found but are required"); } if( restrictedParams!=null ) { for( Map.Entry<String,Set<String>> entry : restrictedParams.entrySet() ) { String name = entry.getKey(); Set<String> options = entry.getValue(); Chunk chunk = dynamicArgs.get(name); if( chunk!=null && !(chunk==Chunk.NULL && removeNulls) ) throw new CompileException(stackTrace,"parameter '"+name+"' cannot be dynamic"); String value = staticArgs.get(name); if( value != null && !options.contains(value) ) throw new CompileException(stackTrace,"parameter '"+name+"' cannot be '"+value+"', must be one of "+options); } } } }