KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > dom > InfixExpression


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.core.dom;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18
19 /**
20  * Infix expression AST node type.
21  * <pre>
22  * InfixExpression:
23  * Expression InfixOperator Expression { InfixOperator Expression }
24  * </pre>
25  *
26  * @since 2.0
27  */

28 public class InfixExpression extends Expression {
29
30     /**
31      * Infix operators (typesafe enumeration).
32      * <pre>
33      * InfixOperator:<code>
34      * <b>*</b> TIMES
35      * <b>/</b> DIVIDE
36      * <b>%</b> REMAINDER
37      * <b>+</b> PLUS
38      * <b>-</b> MINUS
39      * <b>&lt;&lt;</b> LEFT_SHIFT
40      * <b>&gt;&gt;</b> RIGHT_SHIFT_SIGNED
41      * <b>&gt;&gt;&gt;</b> RIGHT_SHIFT_UNSIGNED
42      * <b>&lt;</b> LESS
43      * <b>&gt;</b> GREATER
44      * <b>&lt;=</b> LESS_EQUALS
45      * <b>&gt;=</b> GREATER_EQUALS
46      * <b>==</b> EQUALS
47      * <b>!=</b> NOT_EQUALS
48      * <b>^</b> XOR
49      * <b>&amp;</b> AND
50      * <b>|</b> OR
51      * <b>&amp;&amp;</b> CONDITIONAL_AND
52      * <b>||</b> CONDITIONAL_OR</code>
53      * </pre>
54      */

55     public static class Operator {
56     
57         /**
58          * The token for the operator.
59          */

60         private String JavaDoc token;
61         
62         /**
63          * Creates a new infix operator with the given token.
64          * <p>
65          * Note: this constructor is private. The only instances
66          * ever created are the ones for the standard operators.
67          * </p>
68          *
69          * @param token the character sequence for the operator
70          */

71         private Operator(String JavaDoc token) {
72             this.token = token;
73         }
74         
75         /**
76          * Returns the character sequence for the operator.
77          *
78          * @return the character sequence for the operator
79          */

80         public String JavaDoc toString() {
81             return token;
82         }
83         
84         /** Multiplication "*" operator. */
85         public static final Operator TIMES = new Operator("*");//$NON-NLS-1$
86
/** Division "/" operator. */
87         public static final Operator DIVIDE = new Operator("/");//$NON-NLS-1$
88
/** Remainder "%" operator. */
89         public static final Operator REMAINDER = new Operator("%");//$NON-NLS-1$
90
/** Addition (or string concatenation) "+" operator. */
91         public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
92
/** Subtraction "-" operator. */
93         public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
94
/** Left shift "&lt;&lt;" operator. */
95         public static final Operator LEFT_SHIFT = new Operator("<<");//$NON-NLS-1$
96
/** Signed right shift "&gt;&gt;" operator. */
97         public static final Operator RIGHT_SHIFT_SIGNED = new Operator(">>");//$NON-NLS-1$
98
/** Unsigned right shift "&gt;&gt;&gt;" operator. */
99         public static final Operator RIGHT_SHIFT_UNSIGNED =
100             new Operator(">>>");//$NON-NLS-1$
101
/** Less than "&lt;" operator. */
102         public static final Operator LESS = new Operator("<");//$NON-NLS-1$
103
/** Greater than "&gt;" operator. */
104         public static final Operator GREATER = new Operator(">");//$NON-NLS-1$
105
/** Less than or equals "&lt;=" operator. */
106         public static final Operator LESS_EQUALS = new Operator("<=");//$NON-NLS-1$
107
/** Greater than or equals "&gt=;" operator. */
108         public static final Operator GREATER_EQUALS = new Operator(">=");//$NON-NLS-1$
109
/** Equals "==" operator. */
110         public static final Operator EQUALS = new Operator("==");//$NON-NLS-1$
111
/** Not equals "!=" operator. */
112         public static final Operator NOT_EQUALS = new Operator("!=");//$NON-NLS-1$
113
/** Exclusive OR "^" operator. */
114         public static final Operator XOR = new Operator("^");//$NON-NLS-1$
115
/** Inclusive OR "|" operator. */
116         public static final Operator OR = new Operator("|");//$NON-NLS-1$
117
/** AND "&amp;" operator. */
118         public static final Operator AND = new Operator("&");//$NON-NLS-1$
119
/** Conditional OR "||" operator. */
120         public static final Operator CONDITIONAL_OR = new Operator("||");//$NON-NLS-1$
121
/** Conditional AND "&amp;&amp;" operator. */
122         public static final Operator CONDITIONAL_AND = new Operator("&&");//$NON-NLS-1$
123

124         /**
125          * Map from token to operator (key type: <code>String</code>;
126          * value type: <code>Operator</code>).
127          */

128         private static final Map JavaDoc CODES;
129         static {
130             CODES = new HashMap JavaDoc(20);
131             Operator[] ops = {
132                     TIMES,
133                     DIVIDE,
134                     REMAINDER,
135                     PLUS,
136                     MINUS,
137                     LEFT_SHIFT,
138                     RIGHT_SHIFT_SIGNED,
139                     RIGHT_SHIFT_UNSIGNED,
140                     LESS,
141                     GREATER,
142                     LESS_EQUALS,
143                     GREATER_EQUALS,
144                     EQUALS,
145                     NOT_EQUALS,
146                     XOR,
147                     OR,
148                     AND,
149                     CONDITIONAL_OR,
150                     CONDITIONAL_AND,
151                 };
152             for (int i = 0; i < ops.length; i++) {
153                 CODES.put(ops[i].toString(), ops[i]);
154             }
155         }
156
157         /**
158          * Returns the infix operator corresponding to the given string,
159          * or <code>null</code> if none.
160          * <p>
161          * <code>toOperator</code> is the converse of <code>toString</code>:
162          * that is, <code>Operator.toOperator(op.toString()) == op</code> for
163          * all operators <code>op</code>.
164          * </p>
165          *
166          * @param token the character sequence for the operator
167          * @return the infix operator, or <code>null</code> if none
168          */

169         public static Operator toOperator(String JavaDoc token) {
170             return (Operator) CODES.get(token);
171         }
172         
173     }
174     
175     /**
176      * The "leftOperand" structural property of this node type.
177      * @since 3.0
178      */

179     public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
180         new ChildPropertyDescriptor(InfixExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
181

182     /**
183      * The "operator" structural property of this node type.
184      * @since 3.0
185      */

186     public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
187         new SimplePropertyDescriptor(InfixExpression.class, "operator", InfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
188

189     /**
190      * The "rightOperand" structural property of this node type.
191      * @since 3.0
192      */

193     public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
194         new ChildPropertyDescriptor(InfixExpression.class, "rightOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
195

196     /**
197      * The "extendedOperands" structural property of this node type.
198      * @since 3.0
199      */

200     public static final ChildListPropertyDescriptor EXTENDED_OPERANDS_PROPERTY =
201         new ChildListPropertyDescriptor(InfixExpression.class, "extendedOperands", Expression.class, CYCLE_RISK); //$NON-NLS-1$
202

203     /**
204      * A list of property descriptors (element type:
205      * {@link StructuralPropertyDescriptor}),
206      * or null if uninitialized.
207      */

208     private static final List JavaDoc PROPERTY_DESCRIPTORS;
209     
210     static {
211         List JavaDoc properyList = new ArrayList JavaDoc(5);
212         createPropertyList(InfixExpression.class, properyList);
213         addProperty(LEFT_OPERAND_PROPERTY, properyList);
214         addProperty(OPERATOR_PROPERTY, properyList);
215         addProperty(RIGHT_OPERAND_PROPERTY, properyList);
216         addProperty(EXTENDED_OPERANDS_PROPERTY, properyList);
217         PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
218     }
219
220     /**
221      * Returns a list of structural property descriptors for this node type.
222      * Clients must not modify the result.
223      *
224      * @param apiLevel the API level; one of the
225      * <code>AST.JLS*</code> constants
226
227      * @return a list of property descriptors (element type:
228      * {@link StructuralPropertyDescriptor})
229      * @since 3.0
230      */

231     public static List JavaDoc propertyDescriptors(int apiLevel) {
232         return PROPERTY_DESCRIPTORS;
233     }
234             
235     /**
236      * The infix operator; defaults to InfixExpression.Operator.PLUS.
237      */

238     private InfixExpression.Operator operator = InfixExpression.Operator.PLUS;
239
240     /**
241      * The left operand; lazily initialized; defaults to an unspecified,
242      * but legal, simple name.
243      */

244     private Expression leftOperand = null;
245
246     /**
247      * The right operand; lazily initialized; defaults to an unspecified,
248      * but legal, simple name.
249      */

250     private Expression rightOperand = null;
251
252     /**
253      * The list of extended operand expressions (element type:
254      * <code>Expression</code>). Lazily initialized; defaults to an empty list.
255      */

256     private ASTNode.NodeList extendedOperands = null;
257
258     /**
259      * Creates a new AST node for an infix expression owned by the given
260      * AST. By default, the node has unspecified (but legal) operator,
261      * left and right operands, and an empty list of additional operands.
262      *
263      * @param ast the AST that is to own this node
264      */

265     InfixExpression(AST ast) {
266         super(ast);
267     }
268
269     /* (omit javadoc for this method)
270      * Method declared on ASTNode.
271      */

272     final List JavaDoc internalStructuralPropertiesForType(int apiLevel) {
273         return propertyDescriptors(apiLevel);
274     }
275     
276     /* (omit javadoc for this method)
277      * Method declared on ASTNode.
278      */

279     final Object JavaDoc internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object JavaDoc value) {
280         if (property == OPERATOR_PROPERTY) {
281             if (get) {
282                 return getOperator();
283             } else {
284                 setOperator((Operator) value);
285                 return null;
286             }
287         }
288         // allow default implementation to flag the error
289
return super.internalGetSetObjectProperty(property, get, value);
290     }
291
292     /* (omit javadoc for this method)
293      * Method declared on ASTNode.
294      */

295     final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
296         if (property == LEFT_OPERAND_PROPERTY) {
297             if (get) {
298                 return getLeftOperand();
299             } else {
300                 setLeftOperand((Expression) child);
301                 return null;
302             }
303         }
304         if (property == RIGHT_OPERAND_PROPERTY) {
305             if (get) {
306                 return getRightOperand();
307             } else {
308                 setRightOperand((Expression) child);
309                 return null;
310             }
311         }
312         // allow default implementation to flag the error
313
return super.internalGetSetChildProperty(property, get, child);
314     }
315     
316     /* (omit javadoc for this method)
317      * Method declared on ASTNode.
318      */

319     final List JavaDoc internalGetChildListProperty(ChildListPropertyDescriptor property) {
320         if (property == EXTENDED_OPERANDS_PROPERTY) {
321             return extendedOperands();
322         }
323         // allow default implementation to flag the error
324
return super.internalGetChildListProperty(property);
325     }
326
327     /* (omit javadoc for this method)
328      * Method declared on ASTNode.
329      */

330     final int getNodeType0() {
331         return INFIX_EXPRESSION;
332     }
333
334     /* (omit javadoc for this method)
335      * Method declared on ASTNode.
336      */

337     ASTNode clone0(AST target) {
338         InfixExpression result = new InfixExpression(target);
339         result.setSourceRange(this.getStartPosition(), this.getLength());
340         result.setOperator(getOperator());
341         result.setLeftOperand((Expression) getLeftOperand().clone(target));
342         result.setRightOperand((Expression) getRightOperand().clone(target));
343         if (this.extendedOperands != null) {
344             // be careful not to trigger lazy creation of list
345
result.extendedOperands().addAll(
346                 ASTNode.copySubtrees(target, this.extendedOperands()));
347         }
348         return result;
349     }
350
351     /* (omit javadoc for this method)
352      * Method declared on ASTNode.
353      */

354     final boolean subtreeMatch0(ASTMatcher matcher, Object JavaDoc other) {
355         // dispatch to correct overloaded match method
356
return matcher.match(this, other);
357     }
358
359     /* (omit javadoc for this method)
360      * Method declared on ASTNode.
361      */

362     void accept0(ASTVisitor visitor) {
363         boolean visitChildren = visitor.visit(this);
364         if (visitChildren) {
365             // visit children in normal left to right reading order
366
acceptChild(visitor, getLeftOperand());
367             acceptChild(visitor, getRightOperand());
368             if (this.extendedOperands != null) {
369                 // be careful not to trigger lazy creation of list
370
acceptChildren(visitor, this.extendedOperands);
371             }
372         }
373         visitor.endVisit(this);
374     }
375     
376     /**
377      * Returns the operator of this infix expression.
378      *
379      * @return the infix operator
380      */

381     public InfixExpression.Operator getOperator() {
382         return this.operator;
383     }
384
385     /**
386      * Sets the operator of this infix expression.
387      *
388      * @param operator the infix operator
389      * @exception IllegalArgumentException if the argument is incorrect
390      */

391     public void setOperator(InfixExpression.Operator operator) {
392         if (operator == null) {
393             throw new IllegalArgumentException JavaDoc();
394         }
395         preValueChange(OPERATOR_PROPERTY);
396         this.operator = operator;
397         postValueChange(OPERATOR_PROPERTY);
398     }
399
400     /**
401      * Returns the left operand of this infix expression.
402      *
403      * @return the left operand node
404      */

405     public Expression getLeftOperand() {
406         if (this.leftOperand == null) {
407             // lazy init must be thread-safe for readers
408
synchronized (this) {
409                 if (this.leftOperand == null) {
410                     preLazyInit();
411                     this.leftOperand= new SimpleName(this.ast);
412                     postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
413                 }
414             }
415         }
416         return this.leftOperand;
417     }
418         
419     /**
420      * Sets the left operand of this infix expression.
421      *
422      * @param expression the left operand node
423      * @exception IllegalArgumentException if:
424      * <ul>
425      * <li>the node belongs to a different AST</li>
426      * <li>the node already has a parent</li>
427      * <li>a cycle in would be created</li>
428      * </ul>
429      */

430     public void setLeftOperand(Expression expression) {
431         if (expression == null) {
432             throw new IllegalArgumentException JavaDoc();
433         }
434         ASTNode oldChild = this.leftOperand;
435         preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
436         this.leftOperand = expression;
437         postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
438     }
439
440     /**
441      * Returns the right operand of this infix expression.
442      *
443      * @return the right operand node
444      */

445     public Expression getRightOperand() {
446         if (this.rightOperand == null) {
447             // lazy init must be thread-safe for readers
448
synchronized (this) {
449                 if (this.rightOperand == null) {
450                     preLazyInit();
451                     this.rightOperand= new SimpleName(this.ast);
452                     postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
453                 }
454             }
455         }
456         return this.rightOperand;
457     }
458         
459     /**
460      * Sets the right operand of this infix expression.
461      *
462      * @param expression the right operand node
463      * @exception IllegalArgumentException if:
464      * <ul>
465      * <li>the node belongs to a different AST</li>
466      * <li>the node already has a parent</li>
467      * <li>a cycle in would be created</li>
468      * </ul>
469      */

470     public void setRightOperand(Expression expression) {
471         if (expression == null) {
472             throw new IllegalArgumentException JavaDoc();
473         }
474         ASTNode oldChild = this.rightOperand;
475         preReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
476         this.rightOperand = expression;
477         postReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
478     }
479     
480     /**
481      * Returns where there are any extended operands.
482      *
483      * @return <code>true</code> if there are one or more extended operands,
484      * and <code>false</code> if there are no extended operands
485      */

486     public boolean hasExtendedOperands() {
487         return
488             (this.extendedOperands != null) && this.extendedOperands.size() > 0;
489     }
490     
491     /**
492      * Returns the live list of extended operands.
493      * <p>
494      * The extended operands is the preferred way of representing deeply nested
495      * expressions of the form <code>L op R op R2 op R3...</code> where
496      * the same operator appears between all the operands (the most
497      * common case being lengthy string concatenation expressions). Using
498      * the extended operands keeps the trees from getting too deep; this
499      * decreases the risk is running out of thread stack space at runtime
500      * when traversing such trees.
501      * ((a + b) + c) + d would be translated to:
502      * leftOperand: a
503      * rightOperand: b
504      * extendedOperands: {c, d}
505      * operator: +
506      * </p>
507      *
508      * @return the live list of extended operands
509      * (element type: <code>Expression</code>)
510      */

511     public List JavaDoc extendedOperands() {
512         if (this.extendedOperands == null) {
513             // lazily initialize
514
this.extendedOperands = new ASTNode.NodeList(EXTENDED_OPERANDS_PROPERTY);
515         }
516         return this.extendedOperands;
517     }
518
519     /* (omit javadoc for this method)
520      * Method declared on ASTNode.
521      */

522     int memSize() {
523         // treat Operator as free
524
return BASE_NODE_SIZE + 4 * 4;
525     }
526     
527     /* (omit javadoc for this method)
528      * Method declared on ASTNode.
529      */

530     int treeSize() {
531         return
532             memSize()
533             + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
534             + (this.rightOperand == null ? 0 : getRightOperand().treeSize())
535             + (this.extendedOperands == null ? 0 : extendedOperands.listSize());
536     }
537 }
538
Popular Tags