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.List;
17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
19 import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
22 * String literal nodes.
25 * @noinstantiate This class is not intended to be instantiated by clients.
27 public class StringLiteral extends Expression {
30 * The "escapedValue" structural property of this node type.
33 public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY =
34 new SimplePropertyDescriptor(StringLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
37 * A list of property descriptors (element type:
38 * {@link StructuralPropertyDescriptor}),
39 * or null if uninitialized.
41 private static final List PROPERTY_DESCRIPTORS;
44 List propertyList = new ArrayList(2);
45 createPropertyList(StringLiteral.class, propertyList);
46 addProperty(ESCAPED_VALUE_PROPERTY, propertyList);
47 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
51 * Returns a list of structural property descriptors for this node type.
52 * Clients must not modify the result.
54 * @param apiLevel the API level; one of the
55 * <code>AST.JLS*</code> constants
57 * @return a list of property descriptors (element type:
58 * {@link StructuralPropertyDescriptor})
61 public static List propertyDescriptors(int apiLevel) {
62 return PROPERTY_DESCRIPTORS;
66 * The literal string, including quotes and escapes; defaults to the
67 * literal for the empty string.
69 private String escapedValue = "\"\"";//$NON-NLS-1$
72 * Creates a new unparented string literal node owned by the given AST.
73 * By default, the string literal denotes the empty string.
75 * N.B. This constructor is package-private.
78 * @param ast the AST that is to own this node
80 StringLiteral(AST ast) {
84 /* (omit javadoc for this method)
85 * Method declared on ASTNode.
87 final List internalStructuralPropertiesForType(int apiLevel) {
88 return propertyDescriptors(apiLevel);
91 /* (omit javadoc for this method)
92 * Method declared on ASTNode.
94 final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
95 if (property == ESCAPED_VALUE_PROPERTY) {
97 return getEscapedValue();
99 setEscapedValue((String) value);
103 // allow default implementation to flag the error
104 return super.internalGetSetObjectProperty(property, get, value);
107 /* (omit javadoc for this method)
108 * Method declared on ASTNode.
110 final int getNodeType0() {
111 return STRING_LITERAL;
114 /* (omit javadoc for this method)
115 * Method declared on ASTNode.
117 ASTNode clone0(AST target) {
118 StringLiteral result = new StringLiteral(target);
119 result.setSourceRange(this.getStartPosition(), this.getLength());
120 result.setEscapedValue(getEscapedValue());
124 /* (omit javadoc for this method)
125 * Method declared on ASTNode.
127 final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
128 // dispatch to correct overloaded match method
129 return matcher.match(this, other);
132 /* (omit javadoc for this method)
133 * Method declared on ASTNode.
135 void accept0(ASTVisitor visitor) {
137 visitor.endVisit(this);
141 * Returns the string value of this literal node to the given string
142 * literal token. The token is the sequence of characters that would appear
143 * in the source program, including enclosing double quotes and embedded
146 * @return the string literal token, including enclosing double
147 * quotes and embedded escapes
149 public String getEscapedValue() {
150 return this.escapedValue;
154 * Sets the string value of this literal node to the given string literal
155 * token. The token is the sequence of characters that would appear in the
156 * source program, including enclosing double quotes and embedded escapes.
159 * <li><code>""</code> <code>setLiteral("\"\"")</code></li>
160 * <li><code>"hello world"</code> <code>setLiteral("\"hello world\"")</code></li>
161 * <li><code>"boo\nhoo"</code> <code>setLiteral("\"boo\\nhoo\"")</code></li>
164 * @param token the string literal token, including enclosing double
165 * quotes and embedded escapes
166 * @exception IllegalArgumentException if the argument is incorrect
168 public void setEscapedValue(String token) {
169 // update internalSetEscapedValue(String) if this is changed
171 throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
173 Scanner scanner = this.ast.scanner;
174 char[] source = token.toCharArray();
175 scanner.setSource(source);
176 scanner.resetTo(0, source.length);
178 int tokenType = scanner.getNextToken();
180 case TerminalTokens.TokenNameStringLiteral:
183 throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
185 } catch(InvalidInputException e) {
186 throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
188 preValueChange(ESCAPED_VALUE_PROPERTY);
189 this.escapedValue = token;
190 postValueChange(ESCAPED_VALUE_PROPERTY);
193 /* (omit javadoc for this method)
194 * This method is a copy of setEscapedValue(String) that doesn't do any validation.
196 void internalSetEscapedValue(String token) {
197 preValueChange(ESCAPED_VALUE_PROPERTY);
198 this.escapedValue = token;
199 postValueChange(ESCAPED_VALUE_PROPERTY);
203 * Returns the value of this literal node.
208 * s.setEscapedValue("\"hello\\nworld\"");
209 * assert s.getLiteralValue().equals("hello\nworld");
213 * Note that this is a convenience method that converts from the stored
214 * string literal token returned by <code>getEscapedLiteral</code>.
217 * @return the string value without enclosing double quotes and embedded
219 * @exception IllegalArgumentException if the literal value cannot be converted
221 public String getLiteralValue() {
222 String s = getEscapedValue();
223 int len = s.length();
224 if (len < 2 || s.charAt(0) != '\"' || s.charAt(len-1) != '\"' ) {
225 throw new IllegalArgumentException();
228 Scanner scanner = this.ast.scanner;
229 char[] source = s.toCharArray();
230 scanner.setSource(source);
231 scanner.resetTo(0, source.length);
233 int tokenType = scanner.getNextToken();
235 case TerminalTokens.TokenNameStringLiteral:
236 return scanner.getCurrentStringLiteral();
238 throw new IllegalArgumentException();
240 } catch(InvalidInputException e) {
241 throw new IllegalArgumentException();
246 * Sets the value of this literal node.
251 * s.setLiteralValue("hello\nworld");
252 * assert s.getEscapedValue("\"hello\\nworld\"");
253 * assert s.getLiteralValue().equals("hello\nworld");
257 * Note that this is a convenience method that converts to the stored
258 * string literal token acceptable to <code>setEscapedLiteral</code>.
261 * @param value the string value without enclosing double quotes and
263 * @exception IllegalArgumentException if the argument is incorrect
265 public void setLiteralValue(String value) {
267 throw new IllegalArgumentException();
269 int len = value.length();
270 StringBuffer b = new StringBuffer(len + 2);
272 b.append("\""); // opening delimiter //$NON-NLS-1$
273 for (int i = 0; i < len; i++) {
274 char c = value.charAt(i);
277 b.append("\\b"); //$NON-NLS-1$
280 b.append("\\t"); //$NON-NLS-1$
283 b.append("\\n"); //$NON-NLS-1$
286 b.append("\\f"); //$NON-NLS-1$
289 b.append("\\r"); //$NON-NLS-1$
292 b.append("\\\""); //$NON-NLS-1$
295 b.append("\\\'"); //$NON-NLS-1$
298 b.append("\\\\"); //$NON-NLS-1$
301 b.append("\\0"); //$NON-NLS-1$
304 b.append("\\1"); //$NON-NLS-1$
307 b.append("\\2"); //$NON-NLS-1$
310 b.append("\\3"); //$NON-NLS-1$
313 b.append("\\4"); //$NON-NLS-1$
316 b.append("\\5"); //$NON-NLS-1$
319 b.append("\\6"); //$NON-NLS-1$
322 b.append("\\7"); //$NON-NLS-1$
328 b.append("\""); // closing delimiter //$NON-NLS-1$
329 setEscapedValue(b.toString());
331 /* (omit javadoc for this method)
332 * Method declared on ASTNode.
335 int size = BASE_NODE_SIZE + 1 * 4 + stringSize(escapedValue);
339 /* (omit javadoc for this method)
340 * Method declared on ASTNode.