blob: 1f60b9fc5ad32ae5d46e0c6d8dde10b6f22d90fd [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.royale.compiler.internal.tree.as;
import antlr.Token;
import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.internal.parsing.as.ASToken;
import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.ILiteralNode;
/**
* ActionScript parse tree node representing a literal (e.g. "blah" or true or
* 12)
*/
public class LiteralNode extends ExpressionNodeBase implements ILiteralNode
{
/**
* Constructor.
*
* @param type The type of the literal.
* @param value The value of the literal.
*/
public LiteralNode(LiteralType type, String value)
{
super();
this.type = type;
this.value = value;
}
/**
* Constructor.
*
* @param type type of the literal
* @param t token
*/
public LiteralNode(LiteralType type, Token t)
{
this(type, ((IASToken)t).getText());
span(t);
}
/**
* Constructor.
*
* @param type type of the literal
* @param value value of the literal
* @param sourceLocation object that stores location information of the
* literal
*/
public LiteralNode(LiteralType type, String value, SourceLocation sourceLocation)
{
this(type, value);
setSourceLocation(sourceLocation);
}
/**
* Constructor.
*
* @param t Token with text and source location.
* @param type Literal type
*/
public LiteralNode(ASToken t, LiteralType type)
{
this(type, t.getText());
value = t.getText();
span((Token)t);
}
/**
* Copy constructor.
*
* @param other The node to copy.
*/
protected LiteralNode(LiteralNode other)
{
super(other);
this.type = other.type;
this.value = other.value;
this.synthetic = other.synthetic;
}
/**
* Type of the literal (e.g. Boolean or String)
*/
protected LiteralType type;
protected String value;
private boolean synthetic;
//
// NodeBase overrides
//
@Override
public ASTNodeID getNodeID()
{
switch (type)
{
case ARRAY:
return ASTNodeID.LiteralArrayID;
case BOOLEAN:
return ASTNodeID.LiteralBooleanID;
case NULL:
return ASTNodeID.LiteralNullID;
case NUMBER:
return ASTNodeID.LiteralNumberID;
case OBJECT:
return ASTNodeID.LiteralObjectID;
case REGEXP:
return ASTNodeID.LiteralRegexID;
case STRING:
return ASTNodeID.LiteralStringID;
case VOID:
return ASTNodeID.LiteralVoidID;
case XML:
return ASTNodeID.LiteralXMLID;
}
return ASTNodeID.LiteralID;
}
@Override
public void normalize(boolean fillInOffsets)
{
// do nothing
}
/*
* For debugging only.
* Builds a string such as <code>String "Hello"</code>
* from the literal's type and value.
*/
@Override
protected boolean buildInnerString(StringBuilder sb)
{
String type = getLiteralType().getType().getName();
boolean isString = type.equals(IASLanguageConstants.String);
sb.append(type);
sb.append(' ');
if (isString)
sb.append('"');
sb.append(getValue());
if (isString)
sb.append('"');
return true;
}
//
// FixedChildrenNode overrides
//
@Override
public boolean isTerminal()
{
return true;
}
//
// ExpressionNodeBase overrides
//
@Override
public ITypeDefinition resolveType(ICompilerProject project)
{
LiteralType l = getLiteralType();
return project.getBuiltinType(l.getType());
}
@Override
protected LiteralNode copy()
{
return new LiteralNode(this);
}
@Override
public boolean isDynamicExpression(ICompilerProject project)
{
return false;
}
//
// ILiteralNode implementations
//
@Override
public LiteralType getLiteralType()
{
return type;
}
@Override
public String getValue()
{
return this.getValue(false);
}
@Override
public String getValue(boolean rawValue)
{
String retVal = value;
if (type == LiteralType.STRING)
{
// Note: MXML can create LiteralNodes of type STRING
// where value is null, to represent a null string.
// This happens in a case like <fx:String id="s"/>,
// which sets s to null in MXML 2009.
if (rawValue || retVal == null || retVal.length() == 0)
return retVal;
// Assuming the intent here was to be robust in the face of malformed strings
switch (retVal.charAt(0))
{
case '"':
case '\'':
{
retVal = retVal.substring(1);
}
}
if (retVal.length() >= 1)
{
switch (retVal.charAt(retVal.length() - 1))
{
case '"':
case '\'':
{
retVal = retVal.substring(0, retVal.length() - 1);
}
}
}
else
{
return "";
}
}
return retVal;
}
//
// Other methods
//
/**
* Returns whether this node is synthetic. A synthetic node is one that is
* generated by the parser during parsing, and does not exist in source.
*
* @return true if synthetic
*/
public boolean isSynthetic()
{
return synthetic;
}
/**
* Sets whether this node is synthetic. A synthetic node is one that is
* generated by the parser during parsing, and does not exist in source. A
* common synthetic literal node would be the result of the evaluation of a
* config expression
*
* @param synthetic true if this node is synthetic
*/
public void setSynthetic(boolean synthetic)
{
this.synthetic = synthetic;
}
}