/*
* @(#)$Id: ExpressionPrinter.java,v 1.16 2001/10/18 23:52:11 Bear Exp $
*
* Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package com.sun.msv.grammar.util;
import com.sun.msv.grammar.*;
/**
* creates a string representation of the expression.
*
* useful for debug and dump.
*
* @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a>
*/
public class ExpressionPrinter implements ExpressionVisitor {
/** in this mode, reference to other expression is
* one of the terminal symbol of stringnization.
*
* Suitable to dump the entire grammar
*/
public final static int FRAGMENT = 0x001;
/** in this mode, element declaration is
* one of the terminal symbol of stringnization.
*
* Suitable to dump the content model of element declarations.
*/
public final static int CONTENTMODEL = 0x002;
// singleton access
public static ExpressionPrinter fragmentInstance = new ExpressionPrinter(FRAGMENT);
public static ExpressionPrinter contentModelInstance = new ExpressionPrinter(CONTENTMODEL);
public static ExpressionPrinter smallestInstance = new ExpressionPrinter(CONTENTMODEL|FRAGMENT);
public static String printFragment(Expression exp) {
return (String)exp.visit(fragmentInstance);
}
public static String printContentModel(Expression exp) {
return (String)exp.visit(contentModelInstance);
}
public static String printSmallest(Expression exp) {
return (String)exp.visit(smallestInstance);
}
/** this flag controls how expression will be stringnized */
protected final int mode;
protected ExpressionPrinter( int mode ) { this.mode = mode; }
/** dumps all the contents of ReferenceContainer.
*
* this method is a useful piece to dump the entire grammar.
*/
public String printRefContainer( ReferenceContainer cont ) {
String r="";
java.util.Iterator itr = cont.iterator();
while( itr.hasNext() ) {
ReferenceExp exp = (ReferenceExp)itr.next();
r += exp.name + " : " + exp.exp.visit(this) + "\n";
}
return r;
}
/** determines whether brackets should be used to represent the pattern */
protected static boolean isComplex( Expression exp ) {
return exp instanceof BinaryExp;
}
protected String printBinary( BinaryExp exp, String op ) {
String r;
if( exp.exp1.getClass()==exp.getClass() || !isComplex(exp.exp1) )
r = (String)exp.exp1.visit(this);
else
r = "("+exp.exp1.visit(this)+")";
r+=op;
if( !isComplex(exp.exp2) )
r+=exp.exp2.visit(this);
else
r+="("+exp.exp2.visit(this)+")";
return r;
}
public Object onAttribute( AttributeExp exp ) {
return "@"+exp.nameClass.toString()+"<"+exp.exp.visit(this)+">";
}
private Object optional( Expression exp ) {
if( exp instanceof OneOrMoreExp ) {
OneOrMoreExp ome = (OneOrMoreExp)exp;
if( isComplex(ome.exp) ) return "("+ome.exp.visit(this)+")*";
else return ome.exp.visit(this)+"*";
} else {
if( isComplex(exp) ) return "("+exp.visit(this)+")?";
else return exp.visit(this)+"?";
}
}
public Object onChoice( ChoiceExp exp ) {
if( exp.exp1==Expression.epsilon ) return optional(exp.exp2);
if( exp.exp2==Expression.epsilon ) return optional(exp.exp1);
return printBinary(exp,"|");
}
public Object onConcur( ConcurExp exp ) {
return printBinary(exp,"&");
}
public Object onInterleave( InterleaveExp exp ){
return printBinary(exp,"^");
}
public Object onElement( ElementExp exp ) {
if( (mode&CONTENTMODEL)!=0 )
return exp.getNameClass().toString();
else
return exp.getNameClass().toString()+"<"+exp.contentModel.visit(this)+">";
}
public Object onOneOrMore( OneOrMoreExp exp ) {
if( isComplex(exp.exp) ) return "("+exp.exp.visit(this)+")+";
else return exp.exp.visit(this)+"+";
}
public Object onMixed( MixedExp exp ) {
return "mixed["+exp.exp.visit(this)+"]";
}
public Object onList( ListExp exp ) {
return "list["+exp.exp.visit(this)+"]";
}
public Object onEpsilon() {
return "#epsilon";
}
public Object onNullSet() {
return "#nullSet";
}
public Object onAnyString() {
return "<anyString>";
}
public Object onSequence( SequenceExp exp ) {
return printBinary(exp,",");
}
public Object onData( DataExp exp ) {
return "$"+exp.name.localName;
}
public Object onValue( ValueExp exp ) {
return "$$"+exp.value;
}
public Object onOther( OtherExp exp ) {
return exp.printName()+"["+exp.exp.visit(this)+"]";
}
public Object onRef( ReferenceExp exp ) {
if( (mode&FRAGMENT)!=0 ) return "{%"+exp.name+"}";
else return "("+exp.exp.visit(this)+")";
}
}