001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.List;
015: import java.util.Map;
016:
017: /**
018: * Prefix expression AST node type.
019: *
020: * <pre>
021: * PrefixExpression:
022: * PrefixOperator Expression
023: * </pre>
024: *
025: * @since 2.0
026: */
027: public class PrefixExpression extends Expression {
028:
029: /**
030: * Prefix operators (typesafe enumeration).
031: * <pre>
032: * PrefixOperator:
033: * <b><code>++</code></b> <code>INCREMENT</code>
034: * <b><code>--</code></b> <code>DECREMENT</code>
035: * <b><code>+</code></b> <code>PLUS</code>
036: * <b><code>-</code></b> <code>MINUS</code>
037: * <b><code>~</code></b> <code>COMPLEMENT</code>
038: * <b><code>!</code></b> <code>NOT</code>
039: * </pre>
040: */
041: public static class Operator {
042:
043: /**
044: * The token for the operator.
045: */
046: private String token;
047:
048: /**
049: * Creates a new prefix operator with the given token.
050: * <p>
051: * Note: this constructor is private. The only instances
052: * ever created are the ones for the standard operators.
053: * </p>
054: *
055: * @param token the character sequence for the operator
056: */
057: private Operator(String token) {
058: this .token = token;
059: }
060:
061: /**
062: * Returns the character sequence for the operator.
063: *
064: * @return the character sequence for the operator
065: */
066: public String toString() {
067: return token;
068: }
069:
070: /** Prefix increment "++" operator. */
071: public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
072: /** Prefix decrement "--" operator. */
073: public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
074: /** Unary plus "+" operator. */
075: public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
076: /** Unary minus "-" operator. */
077: public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
078: /** Bitwise complement "~" operator. */
079: public static final Operator COMPLEMENT = new Operator("~");//$NON-NLS-1$
080: /** Logical complement "!" operator. */
081: public static final Operator NOT = new Operator("!");//$NON-NLS-1$
082:
083: /**
084: * Map from token to operator (key type: <code>String</code>;
085: * value type: <code>Operator</code>).
086: */
087: private static final Map CODES;
088: static {
089: CODES = new HashMap(20);
090: Operator[] ops = { INCREMENT, DECREMENT, PLUS, MINUS,
091: COMPLEMENT, NOT, };
092: for (int i = 0; i < ops.length; i++) {
093: CODES.put(ops[i].toString(), ops[i]);
094: }
095: }
096:
097: /**
098: * Returns the prefix operator corresponding to the given string,
099: * or <code>null</code> if none.
100: * <p>
101: * <code>toOperator</code> is the converse of <code>toString</code>:
102: * that is, <code>Operator.toOperator(op.toString()) == op</code> for
103: * all operators <code>op</code>.
104: * </p>
105: *
106: * @param token the character sequence for the operator
107: * @return the prefix operator, or <code>null</code> if none
108: */
109: public static Operator toOperator(String token) {
110: return (Operator) CODES.get(token);
111: }
112: }
113:
114: /**
115: * The "operator" structural property of this node type.
116: * @since 3.0
117: */
118: public static final SimplePropertyDescriptor OPERATOR_PROPERTY = new SimplePropertyDescriptor(
119: PrefixExpression.class,
120: "operator", PrefixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
121:
122: /**
123: * The "operand" structural property of this node type.
124: * @since 3.0
125: */
126: public static final ChildPropertyDescriptor OPERAND_PROPERTY = new ChildPropertyDescriptor(
127: PrefixExpression.class,
128: "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
129:
130: /**
131: * A list of property descriptors (element type:
132: * {@link StructuralPropertyDescriptor}),
133: * or null if uninitialized.
134: */
135: private static final List PROPERTY_DESCRIPTORS;
136:
137: static {
138: List propertyList = new ArrayList(3);
139: createPropertyList(PrefixExpression.class, propertyList);
140: addProperty(OPERATOR_PROPERTY, propertyList);
141: addProperty(OPERAND_PROPERTY, propertyList);
142: PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
143: }
144:
145: /**
146: * Returns a list of structural property descriptors for this node type.
147: * Clients must not modify the result.
148: *
149: * @param apiLevel the API level; one of the
150: * <code>AST.JLS*</code> constants
151:
152: * @return a list of property descriptors (element type:
153: * {@link StructuralPropertyDescriptor})
154: * @since 3.0
155: */
156: public static List propertyDescriptors(int apiLevel) {
157: return PROPERTY_DESCRIPTORS;
158: }
159:
160: /**
161: * The operator; defaults to an unspecified prefix operator.
162: */
163: private PrefixExpression.Operator operator = PrefixExpression.Operator.PLUS;
164:
165: /**
166: * The operand; lazily initialized; defaults to an unspecified,
167: * but legal, simple name.
168: */
169: private Expression operand = null;
170:
171: /**
172: * Creates a new AST node for an prefix expression owned by the given
173: * AST. By default, the node has unspecified (but legal) operator and
174: * operand.
175: *
176: * @param ast the AST that is to own this node
177: */
178: PrefixExpression(AST ast) {
179: super (ast);
180: }
181:
182: /* (omit javadoc for this method)
183: * Method declared on ASTNode.
184: */
185: final List internalStructuralPropertiesForType(int apiLevel) {
186: return propertyDescriptors(apiLevel);
187: }
188:
189: /* (omit javadoc for this method)
190: * Method declared on ASTNode.
191: */
192: final Object internalGetSetObjectProperty(
193: SimplePropertyDescriptor property, boolean get, Object value) {
194: if (property == OPERATOR_PROPERTY) {
195: if (get) {
196: return getOperator();
197: } else {
198: setOperator((Operator) value);
199: return null;
200: }
201: }
202: // allow default implementation to flag the error
203: return super .internalGetSetObjectProperty(property, get, value);
204: }
205:
206: /* (omit javadoc for this method)
207: * Method declared on ASTNode.
208: */
209: final ASTNode internalGetSetChildProperty(
210: ChildPropertyDescriptor property, boolean get, ASTNode child) {
211: if (property == OPERAND_PROPERTY) {
212: if (get) {
213: return getOperand();
214: } else {
215: setOperand((Expression) child);
216: return null;
217: }
218: }
219: // allow default implementation to flag the error
220: return super .internalGetSetChildProperty(property, get, child);
221: }
222:
223: /* (omit javadoc for this method)
224: * Method declared on ASTNode.
225: */
226: final int getNodeType0() {
227: return PREFIX_EXPRESSION;
228: }
229:
230: /* (omit javadoc for this method)
231: * Method declared on ASTNode.
232: */
233: ASTNode clone0(AST target) {
234: PrefixExpression result = new PrefixExpression(target);
235: result
236: .setSourceRange(this .getStartPosition(), this
237: .getLength());
238: result.setOperator(getOperator());
239: result.setOperand((Expression) getOperand().clone(target));
240: return result;
241: }
242:
243: /* (omit javadoc for this method)
244: * Method declared on ASTNode.
245: */
246: final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
247: // dispatch to correct overloaded match method
248: return matcher.match(this , other);
249: }
250:
251: /* (omit javadoc for this method)
252: * Method declared on ASTNode.
253: */
254: void accept0(ASTVisitor visitor) {
255: boolean visitChildren = visitor.visit(this );
256: if (visitChildren) {
257: // visit children in normal left to right reading order
258: acceptChild(visitor, getOperand());
259: }
260: visitor.endVisit(this );
261: }
262:
263: /**
264: * Returns the operator of this prefix expression.
265: *
266: * @return the operator
267: */
268: public PrefixExpression.Operator getOperator() {
269: return this .operator;
270: }
271:
272: /**
273: * Sets the operator of this prefix expression.
274: *
275: * @param operator the operator
276: * @exception IllegalArgumentException if the argument is incorrect
277: */
278: public void setOperator(PrefixExpression.Operator operator) {
279: if (operator == null) {
280: throw new IllegalArgumentException();
281: }
282: preValueChange(OPERATOR_PROPERTY);
283: this .operator = operator;
284: postValueChange(OPERATOR_PROPERTY);
285: }
286:
287: /**
288: * Returns the operand of this prefix expression.
289: *
290: * @return the operand expression node
291: */
292: public Expression getOperand() {
293: if (this .operand == null) {
294: // lazy init must be thread-safe for readers
295: synchronized (this ) {
296: if (this .operand == null) {
297: preLazyInit();
298: this .operand = new SimpleName(this .ast);
299: postLazyInit(this .operand, OPERAND_PROPERTY);
300: }
301: }
302: }
303: return this .operand;
304: }
305:
306: /**
307: * Sets the operand of this prefix expression.
308: *
309: * @param expression the operand expression node
310: * @exception IllegalArgumentException if:
311: * <ul>
312: * <li>the node belongs to a different AST</li>
313: * <li>the node already has a parent</li>
314: * <li>a cycle in would be created</li>
315: * </ul>
316: */
317: public void setOperand(Expression expression) {
318: if (expression == null) {
319: throw new IllegalArgumentException();
320: }
321: ASTNode oldChild = this .operand;
322: preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
323: this .operand = expression;
324: postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
325: }
326:
327: /* (omit javadoc for this method)
328: * Method declared on ASTNode.
329: */
330: int memSize() {
331: // treat Operator as free
332: return BASE_NODE_SIZE + 2 * 4;
333: }
334:
335: /* (omit javadoc for this method)
336: * Method declared on ASTNode.
337: */
338: int treeSize() {
339: return memSize()
340: + (this .operand == null ? 0 : getOperand().treeSize());
341: }
342: }
|