KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > lsmp > djep > xjep > PrintVisitor


1 /* @author rich
2  * Created on 18-Jun-2003
3  *
4  * This code is covered by a Creative Commons
5  * Attribution, Non Commercial, Share Alike license
6  * <a HREF="http://creativecommons.org/licenses/by-nc-sa/1.0">License</a>
7  */

8
9 package org.lsmp.djep.xjep;
10 //import org.lsmp.djep.matrixParser.*;
11
import org.nfunk.jep.*;
12
13 import java.io.PrintStream JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 /**
16  * Prints an expression.
17  * Prints the expression with lots of brackets.
18  * <tt>((-1.0)/sqrt((1.0-(x^2.0))))</tt>.
19  * To use
20  * <pre>
21  * JEP j = ...; Node in = ...;
22  * TreeUtils tu = new TreeUtils(j);
23  * PrintVisitor pv = new PrintVisitor(tu);
24  * pv.print(in,"x");
25  * </pre>
26  * @author Rich Morris
27  * Created on 20-Jun-2003
28  */

29 public class PrintVisitor extends ErrorCatchingVisitor
30 {
31   /** All brackets are printed. Removes all ambiguity. */
32   public static final int FULL_BRACKET = 1;
33   private int maxLen = -1;
34   protected StringBuffer JavaDoc sb;
35   /** The current mode for printing. */
36 // protected boolean fullBrackets=false;
37
protected int mode=0;
38   private Hashtable JavaDoc specialRules = new Hashtable JavaDoc();
39   
40   /** Creates a visitor to create and print string representations of an expression tree. **/
41
42   public PrintVisitor()
43   {
44 /* this.addSpecialRule(Operator.OP_LIST,new PrintVisitor.PrintRulesI()
45     { public void append(Node node,PrintVisitor pv) throws ParseException
46         { pv.append("[");
47             for(int i=0;i<node.jjtGetNumChildren();++i)
48             {
49                 if(i>0) pv.append(",");
50                 node.jjtGetChild(i).jjtAccept(pv, null);
51             }
52             pv.append("]");
53         }});
54 */

55   }
56
57   
58   /** Prints the tree decending from node with lots of brackets or specified stream. **/
59
60   public void print(Node node,PrintStream JavaDoc out)
61   {
62     sb = new StringBuffer JavaDoc();
63     acceptCatchingErrors(node,null);
64     if(maxLen == -1)
65         out.print(sb);
66     else
67     {
68         while(true) {
69             if(sb.length() < maxLen) {
70                 out.print(sb);
71                 return;
72             }
73             int pos = maxLen-2;
74             for(int i=maxLen-2;i>=0;--i) {
75                 char c = sb.charAt(i);
76                 if(c == '+' || c == '-' || c == '*' || c == '/'){
77                     pos = i; break;
78                 }
79             }
80             //out.println("<"+sb.substring(0,pos+10)+">");
81
out.println(sb.substring(0,pos+1));
82             sb.delete(0,pos+1);
83         }
84     }
85   }
86
87   /** Prints on System.out. */
88   public void print(Node node) { print(node,System.out); }
89     
90   /** Prints the tree decending from node with a newline at end. **/
91
92   public void println(Node node,PrintStream JavaDoc out)
93   {
94     print(node,out);
95     out.println("");
96   }
97
98   /** Prints on System.out. */
99   public void println(Node node) { println(node,System.out); }
100
101   /** returns a String representation of the equation. */
102   
103   public String JavaDoc toString(Node node)
104   {
105     sb = new StringBuffer JavaDoc();
106     acceptCatchingErrors(node,null);
107     return sb.toString();
108   }
109   
110     /**
111      * This interface specifies the method needed to implement a special print rule.
112      * A special rule must implement the append method, which should
113      * call pv.append to add data to the output. For example
114      * <pre>
115      * pv.addSpecialRule(Operator.OP_LIST,new PrintVisitor.PrintRulesI()
116      * {
117      * public void append(Node node,PrintVisitor pv) throws ParseException
118      * {
119      * pv.append("[");
120      * for(int i=0;i<node.jjtGetNumChildren();++i)
121      * {
122      * if(i>0) pv.append(",");
123      * node.jjtGetChild(i).jjtAccept(pv, null);
124      * }
125      * pv.append("]");
126      * }});
127      * </pre>
128      * @author Rich Morris
129      * Created on 21-Feb-2004
130      */

131   public interface PrintRulesI
132   {
133     /** The method called to append data for the rule. **/
134     public void append(Node node,PrintVisitor pv) throws ParseException;
135   }
136
137   /** Add a string to buffer. Classes implementing PrintRulesI
138    * should call this add the */

139   public void append(String JavaDoc s) { sb.append(s); }
140
141   /** Adds a special print rule to be added for a given operator.
142    * TODO Allow special rules for other functions, i.e. not operators. */

143   public void addSpecialRule(Operator op,PrintRulesI rules)
144   {
145     specialRules.put(op,rules);
146   }
147
148 /***************** visitor methods ********************************/
149
150 /** print the node with no brackets. */
151 private void printNoBrackets(Node node) throws ParseException
152 {
153     node.jjtAccept(this,null);
154 }
155
156 /** print a node suronded by brackets. */
157 private void printBrackets(Node node) throws ParseException
158 {
159     sb.append("(");
160     printNoBrackets(node);
161     sb.append(")");
162 }
163
164 /** print a unary operator. */
165 private Object JavaDoc visitUnary(ASTFunNode node, Object JavaDoc data) throws ParseException
166 {
167     Node rhs = node.jjtGetChild(0);
168
169     // now print the node
170
sb.append(node.getOperator().getSymbol());
171     // now the rhs
172
if(rhs instanceof ASTFunNode && ((ASTFunNode) rhs).isOperator())
173         printBrackets(rhs); // -(-3) -(1+2) or !(-3)
174
else
175         printNoBrackets(rhs);
176     
177     return data;
178 }
179
180 public Object JavaDoc visit(ASTFunNode node, Object JavaDoc data) throws ParseException
181 {
182     if(!node.isOperator()) return visitFun(node);
183     if(node instanceof PrintRulesI)
184     {
185         ((PrintRulesI) node).append(node,this);
186         return null;
187     }
188     if(node.getOperator()==null)
189     {
190         throw new ParseException("Null operator in print for "+node);
191     }
192     if(specialRules.containsKey(node.getOperator()))
193     {
194         ((PrintRulesI) specialRules.get(node.getOperator())).append(node,this);
195         return null;
196     }
197     if(node.getPFMC() instanceof org.nfunk.jep.function.List)
198     {
199         append("[");
200             for(int i=0;i<node.jjtGetNumChildren();++i)
201             {
202                 if(i>0) append(",");
203                 node.jjtGetChild(i).jjtAccept(this, null);
204             }
205             append("]");
206         return null;
207     }
208         
209     if(((XOperator) node.getOperator()).isUnary())
210         return visitUnary(node,data);
211     if(((XOperator) node.getOperator()).isBinary())
212     {
213         Node lhs = node.jjtGetChild(0);
214         Node rhs = node.jjtGetChild(1);
215         XOperator top = (XOperator) node.getOperator();
216     
217         if((mode & FULL_BRACKET)!= 0)
218         {
219             printBrackets(lhs);
220         }
221         else if(lhs instanceof ASTFunNode && ((ASTFunNode) lhs).isOperator())
222         {
223             XOperator lhsop = (XOperator) ((ASTFunNode) lhs).getOperator();
224             if(top == lhsop)
225             {
226                 if(top.getBinding() == XOperator.LEFT // (1-2)-3 -> 1-2-3
227
&& top.isAssociative() )
228                         printNoBrackets(lhs);
229                 else if(top.useBindingForPrint())
230                         printNoBrackets(lhs);
231                 else
232                         printBrackets(lhs); // (1=2)=3 -> (1=2)=3
233
}
234             else if(top.getPrecedence() == lhsop.getPrecedence())
235             {
236                 if(lhsop.getBinding() == XOperator.LEFT && lhsop.isAssociative())
237                         printNoBrackets(lhs);
238                 else if(lhsop.useBindingForPrint())
239                         printNoBrackets(lhs);
240                 else printBrackets(lhs);
241             } // (1=2)=3 -> (1=2)=3
242

243             else if(top.getPrecedence() > lhsop.getPrecedence()) // (1*2)+3
244
printNoBrackets(lhs);
245             else
246                         printBrackets(lhs);
247         }
248         else
249             printNoBrackets(lhs);
250         
251         // now print the node
252
sb.append(node.getOperator().getSymbol());
253         // now the rhs
254

255         if((mode & FULL_BRACKET)!= 0)
256         {
257             printBrackets(rhs);
258         }
259         else if(rhs instanceof ASTFunNode && ((ASTFunNode) rhs).isOperator())
260         {
261             XOperator rhsop = (XOperator) ((ASTFunNode) rhs).getOperator();
262             if(top == rhsop)
263             {
264                 if(top.getBinding() == XOperator.RIGHT // 1=(2=3) -> 1=2=3
265
|| top.isAssociative() ) // 1+(2-3) -> 1+2-3
266
printNoBrackets(rhs);
267                 else
268                         printBrackets(rhs); // 1-(2+3) -> 1-(2-3)
269
}
270             else if(top.getPrecedence() == rhsop.getPrecedence())
271             {
272                 if(top.getBinding() == XOperator.LEFT && top.isAssociative() ) // 1+(2-3) -> 1+2-3)
273
printNoBrackets(rhs); // a+(b-c) -> a+b-c
274
else
275                     printBrackets(rhs); // a-(b+c) -> a-(b+c)
276
}
277             else if(top.getPrecedence() > rhsop.getPrecedence()) // 1+(2*3) -> 1+2*3
278
printNoBrackets(rhs);
279             else
280                         printBrackets(rhs);
281         }
282         else
283             printNoBrackets(rhs);
284     }
285     return null;
286 }
287
288 /** prints a standard function: fun(arg,arg) */
289 private Object JavaDoc visitFun(ASTFunNode node) throws ParseException
290 {
291     sb.append(node.getName()+"(");
292     for(int i=0;i<node.jjtGetNumChildren();++i)
293     {
294         if(i>0) sb.append(",");
295         node.jjtGetChild(i).jjtAccept(this, null);
296     }
297     sb.append(")");
298
299     return null;
300 }
301
302   public Object JavaDoc visit(ASTVarNode node, Object JavaDoc data) throws ParseException {
303     sb.append(node.getName());
304     return data;
305   }
306
307   public Object JavaDoc visit(ASTConstant node, Object JavaDoc data) {
308     sb.append(node.getValue());
309     return data;
310   }
311     /**
312      * Return the current print mode.
313      */

314     public int getMode() {
315         return mode;
316     }
317     
318     /**
319      * Set printing mode.
320      * In full bracket mode the brackets each element in the tree will be suronded
321      * by brackets to indicate the tree structure.
322      * In the default mode, (full bracket off) the number of brackets is
323      * minimised so (x+y)+z will be printed as x+y+z.
324      * @param mode which flags to change, typically FULL_BRACKET
325      * @param flag whether to switch this mode on or off
326      */

327     public void setMode(int mode,boolean flag) {
328         if(flag)
329             this.mode |= mode;
330         else
331             this.mode ^= mode;
332     }
333
334 /**
335  * @return the maximum length printed per line
336  */

337 public int getMaxLen() {
338     return maxLen;
339 }
340
341 /**
342  * Sets the maximium length printed per line.
343  * If the value is not -1 then the string will be broken into chunks
344  * each of which is less than the max lenght.
345  * @param i the maximum length
346  */

347 public void setMaxLen(int i) {
348     maxLen = i;
349 }
350
351 }
352
353 /*end*/
354
Popular Tags