/* * @(#)$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)+")"; } }