package org.kohsuke.bali.automaton.builder; import com.sun.msv.grammar.*; import com.sun.msv.grammar.util.NameClassSimplifier; /** * Find all AttributeExps inside the given expression * and combine them into a single NameClass. * * @author Kohsuke Kawaguchi (kk@kohsuke.org) */ class AttNameCombiner implements ExpressionVisitor { /** * Obtains the all permitted attributes as a name class. */ public static NameClass collect( Expression exp ) { return NameClassSimplifier.simplify((NameClass)exp.visit(theInstance)); } private static final AttNameCombiner theInstance = new AttNameCombiner(); /** * Empty name class. * * Used very frequently so this field is used as a constant. */ private final NameClass noName = new NotNameClass(AnyNameClass.theInstance); public Object onAttribute(AttributeExp att) { return att.nameClass; } public Object onChoice(ChoiceExp exp) { return binary(exp); } public Object onInterleave(InterleaveExp exp) { return binary(exp); } public Object onSequence(SequenceExp exp) { return binary(exp); } private NameClass binary( BinaryExp exp ) { NameClass nc1 = (NameClass)exp.exp1.visit(this); NameClass nc2 = (NameClass)exp.exp2.visit(this); if( nc1==noName ) return nc2; if( nc2==noName ) return nc1; return new ChoiceNameClass(nc1,nc2); } public Object onConcur(ConcurExp exp) { throw new InternalError("<concur> is not supported"); } public Object onData(DataExp exp) { return noName; } public Object onElement(ElementExp exp) { return noName; } public Object onEpsilon() { return noName; } public Object onList(ListExp exp) { return noName; } public Object onMixed(MixedExp exp) { return exp.exp.visit(this); } public Object onNullSet() { throw new InternalError(); } public Object onOneOrMore(OneOrMoreExp exp) { return exp.exp.visit(this); } public Object onOther(OtherExp exp) { return exp.exp.visit(this); } public Object onRef(ReferenceExp exp) { return exp.exp.visit(this); } public Object onValue(ValueExp exp) { return noName; } public Object onAnyString() { return noName; } };