/*******************************************************************************
* Copyright (c) 2007, 2008 Edgar Espina.
* 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
*
*******************************************************************************/
package org.deved.antlride.internal.core.model;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.deved.antlride.core.model.ElementKind;
import org.deved.antlride.core.model.IGrammar;
import org.deved.antlride.core.model.IModelElement;
import org.deved.antlride.core.model.IReference;
import org.deved.antlride.core.model.IRule;
import org.deved.antlride.core.model.IRuleAction;
import org.deved.antlride.core.model.ISourceElement;
import org.deved.antlride.core.model.IStatement;
import org.deved.antlride.core.model.ITargetAction;
import org.deved.antlride.core.model.ast.IModelElementVisitor;
import org.deved.antlride.core.model.ast.criteria.IModelElementCriteria;
import org.deved.antlride.core.model.ast.criteria.ModelElementCriteriaFactory;
public class ATargetAction extends AAbstractModelElement implements
ITargetAction {
private static final IReference[] NO_REFERENCES = new IReference[0];
private String action;
private IReference[] references;
public ATargetAction(IModelElement parent, ISourceElement action) {
super(parent);
this.action = action.getText();
setSourceStart(action.sourceStart());
setSourceEnd(action.sourceEnd());
//TODO: review the search references code
references = NO_REFERENCES;
// System.out.println(getText());
}
public <E> E getAdapter(Class<E> adapter) {
if (adapter == ITargetAction.class)
return adapter.cast(this);
if (adapter == IRule.class && getEnclosingRule() != null)
return adapter.cast(getEnclosingRule().getAdapter(adapter));
return getParent().getAdapter(adapter);
}
public IRule getEnclosingRule() {
IRule rule = null;
IModelElement element = getParent();
if (element instanceof IStatement) {
IStatement statement = (IStatement) element;
rule = statement.getEnclosingRule();
} else if (element instanceof IRuleAction) {
IRuleAction ruleAction = (IRuleAction) element;
rule = (IRule) ruleAction.getParent();
}
return rule;
}
public EBNF getEbnfOperator() {
return EBNF.NONE;
}
public IReference[] getReferences() {
if (references == null) {
references = processAction(getParent(), getText(), sourceStart());
}
return references;
}
public String getText() {
return action;
}
public ElementKind getElementKind() {
return ElementKind.TARGET_ACTION;
}
public String getElementName() {
return "<{...}>";
}
public void traverse(IModelElementVisitor visitor) {
if (visitor.visitTargetAction(this)) {
IReference[] references = getReferences();
if (references.length > 0) {
for (int i = 0; i < references.length; i++) {
references[i].traverse(visitor);
}
}
visitor.endvisitTargetAction(this);
}
}
// private IScope
private IReference[] processAction(IModelElement element, String text,
int sourceStart) {
int offset = sourceStart + 1;
String split = " \t\n\r\f=,;+-*/^()!&|<>%[]{}";
List<IReference> references = new ArrayList<IReference>(5);
StringTokenizer tokenizer = new StringTokenizer(text, split, true);
// IRule rule = getEnclosingRule();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
int k = token.indexOf('$');
if (split.indexOf(token) == -1 && k != -1) {
// int start = offset + k;
int index = token.indexOf(":", k);
if (index != -1) {
// scope
int i0 = token.indexOf("::", k);
if (i0 == -1) {
i0 = index;
}
// String scopeName = token.substring(k + 1, index);
// IModelElement scope = findScope(element, scopeName);
// int scopeLen = start + scopeName.length();
// IReference scopeReference = new AReference(this,
// new ASourceElement(scopeName, start, scopeLen),
// scope);
// references.add(scopeReference);
// int attrStart = scopeLen + 2;
// int i1 = attrStart - offset + 1;
// int i2 = token.indexOf('.');
// String attrName = "";
// try {
// if (i2 == -1) {
// attrName = token.substring(i1);
// } else {
// attrName = token.substring(i1, i2);
// }
// } catch (StringIndexOutOfBoundsException ex) {
//
// }
// IScopeAttribute scopeAttribute = findScopeAttribute(scope,
// attrName);
// IReference scopeAttributeReference = new AReference(this,
// new ASourceElement(attrName, attrStart, attrStart
// + attrName.length()), scopeAttribute);
// references.add(scopeAttributeReference);
} else {
// index = token.indexOf('.', k);
// String ruleName = null;
// if (index != -1) {
// ruleName = token.substring(k + 1, index);
// } else {
// ruleName = token.substring(k + 1);
// }
IModelElementCriteria kindCriteria = ModelElementCriteriaFactory
.callOrVariable();
kindCriteria = ModelElementCriteriaFactory.or(kindCriteria,
ModelElementCriteriaFactory
.grammarScopeOrRuleScope());
// IModelElementCriteria criteria = ModelElementCriteriaFactory
// .and(kindCriteria, ModelElementCriteriaFactory
// .nameEquals(ruleName));
// AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
// criteria);
// try to find a var decl
// Object[] elements = findClosestStatement(collector, parent,
// ruleName);
// IModelElement e = null;
// if (elements != null && elements.length > 0) {
// e = (IModelElement) elements[0];
// } else {
// if (ruleName.equals(rule.getElementName())) {
// e = rule;
// }
// }
// IReference reference = new AReference(this,
// new ASourceElement(ruleName, start, start
// + ruleName.length()), e);
// references.add(reference);
}
}
offset += token.length();
}
IReference[] result = NO_REFERENCES;
if (references.size() > 0)
result = references.toArray(new IReference[references.size()]);
references.clear();
return result;
}
// private Object[] findClosestStatement(
// AntlrModelElementCollectorVisitor collector, IModelElement p,
// String elementName) {
// boolean notMatch = true;
// while (notMatch && p.getElementKind() != ElementKind.RULE) {
// collector.accept(p);
// if (collector.getResultSize() > 0) {
// notMatch = false;
// }
// p = p.getParent();
// }
// return notMatch ? null : collector.getResult();
// }
private IModelElement findScope(IModelElement element, String scopeName) {
IModelElement scope = null;
IRule rule = element.getAdapter(IRule.class);
IGrammar grammar = element.getAdapter(IGrammar.class);
// if (element instanceof IStatement) {
// IStatement statement = (IStatement) element;
// rule = statement.getEnclosingRule();
// grammar = (IGrammar) rule.getParent();
// } else if (element instanceof IRule) {
// rule = (IRule) element;
// grammar = (IGrammar) rule.getParent();
// } else if (element instanceof IRuleAction) {
// IRuleAction ruleAction = (IRuleAction) element;
// rule = (IRule) ruleAction.getParent();
// grammar = (IGrammar) rule.getParent();
// } else if (element instanceof IGrammar) {
// grammar = (IGrammar) element;
// }
if (rule != null) {
scope = rule.findScope(scopeName);
if (scope == null) {
scope = rule.findScopeReference(scopeName);
}
}
if (scope == null) {
scope = grammar.findScope(scopeName);
}
return scope;
}
// private IScopeAttribute findScopeAttribute(IModelElement element,
// String scopeAttributeName) {
// if (element == null)
// return null;
// IScope scope = null;
// if (element instanceof IScope) {
// scope = (IScope) element;
// } else if (element instanceof IScopeReference) {
// scope = (IScope) ((IScopeReference) element).getReference();
// }
// IScopeAttribute scopeAttribute = null;
// if (scope != null) {
// scopeAttribute = scope.findAttribute(scopeAttributeName);
// }
// return scopeAttribute;
// }
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
// builder.append('{');
builder.append(getText());
// builder.append('}');
return builder.toString();
}
}