1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.core.dom;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
20 * Prefix expression AST node type.
24 * PrefixOperator Expression
28 * @noinstantiate This class is not intended to be instantiated by clients.
30 public class PrefixExpression extends Expression {
33 * Prefix operators (typesafe enumeration).
36 * <b><code>++</code></b> <code>INCREMENT</code>
37 * <b><code>--</code></b> <code>DECREMENT</code>
38 * <b><code>+</code></b> <code>PLUS</code>
39 * <b><code>-</code></b> <code>MINUS</code>
40 * <b><code>~</code></b> <code>COMPLEMENT</code>
41 * <b><code>!</code></b> <code>NOT</code>
44 public static class Operator {
47 * The token for the operator.
52 * Creates a new prefix operator with the given token.
54 * Note: this constructor is private. The only instances
55 * ever created are the ones for the standard operators.
58 * @param token the character sequence for the operator
60 private Operator(String token) {
65 * Returns the character sequence for the operator.
67 * @return the character sequence for the operator
69 public String toString() {
73 /** Prefix increment "++" operator. */
74 public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
75 /** Prefix decrement "--" operator. */
76 public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
77 /** Unary plus "+" operator. */
78 public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
79 /** Unary minus "-" operator. */
80 public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
81 /** Bitwise complement "~" operator. */
82 public static final Operator COMPLEMENT = new Operator("~");//$NON-NLS-1$
83 /** Logical complement "!" operator. */
84 public static final Operator NOT = new Operator("!");//$NON-NLS-1$
87 * Map from token to operator (key type: <code>String</code>;
88 * value type: <code>Operator</code>).
90 private static final Map CODES;
92 CODES = new HashMap(20);
101 for (int i = 0; i < ops.length; i++) {
102 CODES.put(ops[i].toString(), ops[i]);
107 * Returns the prefix operator corresponding to the given string,
108 * or <code>null</code> if none.
110 * <code>toOperator</code> is the converse of <code>toString</code>:
111 * that is, <code>Operator.toOperator(op.toString()) == op</code> for
112 * all operators <code>op</code>.
115 * @param token the character sequence for the operator
116 * @return the prefix operator, or <code>null</code> if none
118 public static Operator toOperator(String token) {
119 return (Operator) CODES.get(token);
124 * The "operator" structural property of this node type.
127 public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
128 new SimplePropertyDescriptor(PrefixExpression.class, "operator", PrefixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
131 * The "operand" structural property of this node type.
134 public static final ChildPropertyDescriptor OPERAND_PROPERTY =
135 new ChildPropertyDescriptor(PrefixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
138 * A list of property descriptors (element type:
139 * {@link StructuralPropertyDescriptor}),
140 * or null if uninitialized.
142 private static final List PROPERTY_DESCRIPTORS;
145 List propertyList = new ArrayList(3);
146 createPropertyList(PrefixExpression.class, propertyList);
147 addProperty(OPERATOR_PROPERTY, propertyList);
148 addProperty(OPERAND_PROPERTY, propertyList);
149 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
153 * Returns a list of structural property descriptors for this node type.
154 * Clients must not modify the result.
156 * @param apiLevel the API level; one of the
157 * <code>AST.JLS*</code> constants
159 * @return a list of property descriptors (element type:
160 * {@link StructuralPropertyDescriptor})
163 public static List propertyDescriptors(int apiLevel) {
164 return PROPERTY_DESCRIPTORS;
168 * The operator; defaults to an unspecified prefix operator.
170 private PrefixExpression.Operator operator =
171 PrefixExpression.Operator.PLUS;
174 * The operand; lazily initialized; defaults to an unspecified,
175 * but legal, simple name.
177 private Expression operand = null;
180 * Creates a new AST node for an prefix expression owned by the given
181 * AST. By default, the node has unspecified (but legal) operator and
184 * @param ast the AST that is to own this node
186 PrefixExpression(AST ast) {
190 /* (omit javadoc for this method)
191 * Method declared on ASTNode.
193 final List internalStructuralPropertiesForType(int apiLevel) {
194 return propertyDescriptors(apiLevel);
197 /* (omit javadoc for this method)
198 * Method declared on ASTNode.
200 final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
201 if (property == OPERATOR_PROPERTY) {
203 return getOperator();
205 setOperator((Operator) value);
209 // allow default implementation to flag the error
210 return super.internalGetSetObjectProperty(property, get, value);
213 /* (omit javadoc for this method)
214 * Method declared on ASTNode.
216 final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
217 if (property == OPERAND_PROPERTY) {
221 setOperand((Expression) child);
225 // allow default implementation to flag the error
226 return super.internalGetSetChildProperty(property, get, child);
229 /* (omit javadoc for this method)
230 * Method declared on ASTNode.
232 final int getNodeType0() {
233 return PREFIX_EXPRESSION;
236 /* (omit javadoc for this method)
237 * Method declared on ASTNode.
239 ASTNode clone0(AST target) {
240 PrefixExpression result = new PrefixExpression(target);
241 result.setSourceRange(this.getStartPosition(), this.getLength());
242 result.setOperator(getOperator());
243 result.setOperand((Expression) getOperand().clone(target));
247 /* (omit javadoc for this method)
248 * Method declared on ASTNode.
250 final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
251 // dispatch to correct overloaded match method
252 return matcher.match(this, other);
255 /* (omit javadoc for this method)
256 * Method declared on ASTNode.
258 void accept0(ASTVisitor visitor) {
259 boolean visitChildren = visitor.visit(this);
261 // visit children in normal left to right reading order
262 acceptChild(visitor, getOperand());
264 visitor.endVisit(this);
268 * Returns the operator of this prefix expression.
270 * @return the operator
272 public PrefixExpression.Operator getOperator() {
273 return this.operator;
277 * Sets the operator of this prefix expression.
279 * @param operator the operator
280 * @exception IllegalArgumentException if the argument is incorrect
282 public void setOperator(PrefixExpression.Operator operator) {
283 if (operator == null) {
284 throw new IllegalArgumentException();
286 preValueChange(OPERATOR_PROPERTY);
287 this.operator = operator;
288 postValueChange(OPERATOR_PROPERTY);
292 * Returns the operand of this prefix expression.
294 * @return the operand expression node
296 public Expression getOperand() {
297 if (this.operand == null) {
298 // lazy init must be thread-safe for readers
299 synchronized (this) {
300 if (this.operand == null) {
302 this.operand= new SimpleName(this.ast);
303 postLazyInit(this.operand, OPERAND_PROPERTY);
311 * Sets the operand of this prefix expression.
313 * @param expression the operand expression node
314 * @exception IllegalArgumentException if:
316 * <li>the node belongs to a different AST</li>
317 * <li>the node already has a parent</li>
318 * <li>a cycle in would be created</li>
321 public void setOperand(Expression expression) {
322 if (expression == null) {
323 throw new IllegalArgumentException();
325 ASTNode oldChild = this.operand;
326 preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
327 this.operand = expression;
328 postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
331 /* (omit javadoc for this method)
332 * Method declared on ASTNode.
335 // treat Operator as free
336 return BASE_NODE_SIZE + 2 * 4;
339 /* (omit javadoc for this method)
340 * Method declared on ASTNode.
345 + (this.operand == null ? 0 : getOperand().treeSize());