/*******************************************************************************
* Copyright (c) 2008, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IValue;
/**
* Base class for C and C++ enumerators.
*/
public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, IASTAmbiguityParent {
private IASTName name;
private IASTExpression value;
private IValue integralValue;
public ASTEnumerator() {
}
public ASTEnumerator(IASTName name, IASTExpression value) {
setName(name);
setValue(value);
}
protected void copyAbstractEnumerator(ASTEnumerator copy, CopyStyle style) {
copy.setName(name == null ? null : name.copy(style));
copy.setValue(value == null ? null : value.copy(style));
copy.setOffsetAndLength(this);
}
public void setName(IASTName name) {
assertNotFrozen();
this.name = name;
if (name != null) {
name.setParent(this);
name.setPropertyInParent(ENUMERATOR_NAME);
}
}
public IASTName getName() {
return name;
}
public void setValue(IASTExpression expression) {
assertNotFrozen();
this.value = expression;
if (expression != null) {
expression.setParent(this);
expression.setPropertyInParent(ENUMERATOR_VALUE);
}
}
public IASTExpression getValue() {
return value;
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitEnumerators) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
}
}
if (name != null && !name.accept(action)) return false;
if (value != null && !value.accept(action)) return false;
if (action.shouldVisitEnumerators) {
switch (action.leave(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
}
}
return true;
}
public int getRoleForName(IASTName n) {
if (n == name)
return r_definition;
return r_reference;
}
public void replace(IASTNode child, IASTNode other) {
if (child == value) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
value = (IASTExpression) other;
}
}
public IValue getIntegralValue() {
if (integralValue == null) {
IASTNode parent= getParent();
if (parent instanceof IASTInternalEnumerationSpecifier) {
IASTInternalEnumerationSpecifier ies= (IASTInternalEnumerationSpecifier) parent;
if (ies.startValueComputation()) { // prevents infinite recursions
createEnumValues((IASTEnumerationSpecifier) parent);
}
}
if (integralValue == null) {
integralValue= Value.UNKNOWN;
}
}
return integralValue;
}
private void createEnumValues(IASTEnumerationSpecifier parent) {
IASTEnumerator[] etors= parent.getEnumerators();
long cv= -1;
boolean isknown= true;
for (IASTEnumerator etor : etors) {
cv++;
IASTExpression expr= etor.getValue();
if (expr != null) {
IValue val= Value.create(expr, Value.MAX_RECURSION_DEPTH);
Long nv= val.numericalValue();
isknown= false;
if (nv != null) {
isknown= true;
cv= nv.longValue();
}
}
if (etor instanceof ASTEnumerator) {
((ASTEnumerator) etor).integralValue= isknown ? Value.create(cv) : Value.UNKNOWN;
}
}
}
}