/*******************************************************************************
* 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.core.model.ast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.deved.antlride.core.model.ElementKind;
import org.deved.antlride.core.model.IBlock;
import org.deved.antlride.core.model.ICallExpression;
import org.deved.antlride.core.model.ICompositeStatement;
import org.deved.antlride.core.model.IGrammar;
import org.deved.antlride.core.model.IModelElement;
import org.deved.antlride.core.model.IRule;
import org.deved.antlride.core.model.IScope;
import org.deved.antlride.core.model.IStatement;
import org.deved.antlride.core.model.ast.criteria.IModelElementCriteria;
import org.deved.antlride.core.model.ast.criteria.ModelElementCriteriaFactory;
import org.deved.antlride.core.util.AntlrTextHelper;
public class ModelElementQuery {
public static int count(IModelElement element) {
return count(element, null);
}
public static int count(IModelElement element,
IModelElementCriteria criteria) {
ModelElementCounterVisitor visitor = new ModelElementCounterVisitor(
criteria);
visitor.accept(element);
return visitor.getResult();
}
@SuppressWarnings("unchecked")
public static IRule[] collectRules(IGrammar grammar,
boolean searchDependents) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.kind(ElementKind.RULE));
collector.accept(grammar);
Collection<IRule> ruleList = new ArrayList<IRule>(
(Collection<? extends IRule>) Arrays.asList(collector
.getResult()));
for (IGrammar g : grammar.getDependents()) {
collector.accept(g);
ruleList.addAll((Collection<? extends IRule>) Arrays
.asList(collector.getResult()));
}
return ruleList.toArray(new IRule[ruleList.size()]);
}
public static IModelElement getElementAt(IGrammar grammar, int line,
int column) {
String source = grammar.getSource();
int offset = AntlrTextHelper.getOffsetAtLine(source, line) + column;
AntlrModelElementLocator locator = new AntlrModelElementLocator(grammar);
IModelElement element = locator.getElementAt(offset);
return element;
}
public static List<IModelElement> getRuleInvocationStack(
IModelElement element) {
List<IModelElement> elements = new ArrayList<IModelElement>();
Set<IModelElement> temp = new HashSet<IModelElement>();
internalGetRuleInvocationStack(element, temp, elements);
Collections.sort(elements, new Comparator<IModelElement>() {
public int compare(IModelElement e1, IModelElement e2) {
return e2.sourceStart() - e1.sourceEnd();
}
});
IGrammar grammar = element.getAdapter(IGrammar.class);
String source = grammar.getSource();
System.out.println("-----begin stack: ");
for (IModelElement e : elements) {
int line = AntlrTextHelper.getLineAtOffset(source, e.sourceStart());
int offset = AntlrTextHelper.getOffsetAtLine(source, line);
int column = e.sourceStart() - offset + 1;
System.out.println("\t" + e.getElementName() + " at " + line + ": "
+ column);
}
System.out.println("-----end stack: ");
return elements;
}
private static void internalGetRuleInvocationStack(IModelElement element,
Set<IModelElement> processedElements,
Collection<IModelElement> stack) {
if (element == null)
return;
IGrammar grammar = element.getAdapter(IGrammar.class);
if (grammar == null)
return;
IModelElementCriteria criteria = ModelElementCriteriaFactory
.nameEquals(element.getElementName());
AntlrModelElementCollectorVisitor visitor = new AntlrModelElementCollectorVisitor(
criteria);
visitor.setAcceptDuplicates(true);
visitor.accept(grammar);
IModelElement[] elements = visitor.getResult();
for (IModelElement me : elements) {
IRule enclosingRule = me.getAdapter(IRule.class);
if (me != enclosingRule
&& !processedElements.contains(enclosingRule)) {
processedElements.add(enclosingRule);
stack.add(me);
internalGetRuleInvocationStack(enclosingRule,
processedElements, stack);
}
}
}
public static boolean isRuleDeclaration(IModelElement element) {
return element instanceof IRule;
}
public static boolean isRuleInvocation(IModelElement element) {
return (element instanceof ICallExpression)
&& element.getElementName() != null
&& Character.isLowerCase(element.getElementName().charAt(0));
}
public static boolean isInRewriteAlternative(IModelElement element) {
IBlock block = null;
if (element instanceof IBlock) {
block = (IBlock) element;
}
if (block != null && block.isRewritten()) {
return true;
}
if (element.getParent() != null)
return isInRewriteAlternative(element.getParent());
return false;
}
public static IModelElement[] collectRules(IGrammar grammar, String ruleName) {
IModelElementCriteria criteria = ModelElementCriteriaFactory
.ruleOrToken();
if (ruleName != null && ruleName.length() > 0) {
criteria = ModelElementCriteriaFactory.and(criteria,
ModelElementCriteriaFactory.nameStartsWith(ruleName));
}
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.accept(grammar);
return collector.getResult();
}
public static IModelElement[] collectLocalReferences(IRule rule,
int sourcePosition, String referenceName) {
IModelElementCriteria typeCriteria = ModelElementCriteriaFactory.or(
ModelElementCriteriaFactory.callOrVariable(),
ModelElementCriteriaFactory.grammarScopeOrRuleScope());
IModelElementCriteria excludedNames = ModelElementCriteriaFactory
.not(ModelElementCriteriaFactory.charLiteralOrStringLiteral());
IModelElementCriteria criteria = ModelElementCriteriaFactory.and(
ModelElementCriteriaFactory.sourcePosition(sourcePosition - 1),
ModelElementCriteriaFactory.and(typeCriteria, excludedNames));
if (referenceName != null && referenceName.length() > 0) {
IModelElementCriteria swCriteria = ModelElementCriteriaFactory
.nameStartsWith(referenceName);
criteria = ModelElementCriteriaFactory.and(criteria, swCriteria);
}
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.accept(rule);
return collector.getResult();
}
public static IModelElement[] collectScopeAttributes(IScope scope) {
return collectScopeAttributes(scope, null);
}
public static IModelElement[] collectScopeAttributes(IScope scope,
String attributeName) {
IModelElementCriteria criteria = ModelElementCriteriaFactory
.grammarScopeAttributeOrRuleScopeAttribute();
if (attributeName != null && attributeName.length() > 0) {
criteria = ModelElementCriteriaFactory.and(
ModelElementCriteriaFactory.nameStartsWith(attributeName),
criteria);
}
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.accept(scope);
return collector.getResult();
}
public static IModelElement[] collectCalls(IRule owner) {
return collectCalls(owner, true);
}
public static IModelElement[] collectCalls(IRule owner,
boolean acceptDuplicates) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.kind(ElementKind.CALL));
collector.setAcceptDuplicates(true);
collector.accept(owner);
IModelElement[] calls = collector.getResult();
return calls;
}
public static IModelElement[] collectTokens(IGrammar grammar) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.kind(ElementKind.TOKEN));
collector.accept(grammar);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectAllTokens(IGrammar grammar) {
IModelElementCriteria criteria = ModelElementCriteriaFactory.or(
ModelElementCriteriaFactory.or(ModelElementCriteriaFactory
.kind(ElementKind.TOKEN), ModelElementCriteriaFactory
.literalReference()), ModelElementCriteriaFactory
.lexerRule());
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.accept(grammar);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectAlts(ICompositeStatement element) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.kind(ElementKind.ALTERNATIVE));
collector.setAcceptDuplicates(true);
collector.accept(element);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectBlocksOrAlts(
ICompositeStatement element) {
IModelElementCriteria criteria = ModelElementCriteriaFactory.or(
ModelElementCriteriaFactory.kind(ElementKind.ALTERNATIVE),
ModelElementCriteriaFactory.kind(ElementKind.BLOCK));
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.setAcceptDuplicates(true);
collector.accept(element);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectTreeStatements(
ICompositeStatement element) {
IModelElementCriteria criteria = ModelElementCriteriaFactory.or(
ModelElementCriteriaFactory.kind(ElementKind.TREE_STATEMENT),
ModelElementCriteriaFactory.kind(ElementKind.BLOCK));
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
criteria);
collector.setAcceptDuplicates(true);
collector.accept(element);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectLexerRules(IGrammar grammar) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.lexerRule());
collector.accept(grammar);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] collectLiterals(IGrammar grammar) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.literalReference());
collector.accept(grammar);
List<IModelElement> literals = new ArrayList<IModelElement>(Arrays
.asList(collector.getResult()));
IGrammar[] dependents = grammar.getDependents();
for (IGrammar depGrammar : dependents) {
collector.accept(depGrammar);
literals.addAll(Arrays.asList(collector.getResult()));
}
return literals.toArray(new IModelElement[literals.size()]);
}
public static IModelElement[] collectPredicates(IGrammar grammar) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.predicates());
collector.accept(grammar);
IModelElement[] elements = collector.getResult();
return elements;
}
public static String[] collectRuleNamesWithPredicates(IGrammar grammar,
boolean ignorePredicatesInRewriteAlt) {
IRule[] rules = collectRulesWithPredicates(grammar,
ignorePredicatesInRewriteAlt);
String[] ruleNames = new String[rules.length];
for (int i = 0; i < rules.length; i++) {
ruleNames[i] = rules[i].getElementName();
}
return ruleNames;
}
public static IRule[] collectRulesWithPredicates(IGrammar grammar,
boolean ignorePredicatesInRewriteAlt) {
Collection<IRule> rules = new ArrayList<IRule>();
IModelElement[] predicates = collectPredicates(grammar,
ignorePredicatesInRewriteAlt);
for (IModelElement p : predicates) {
IStatement stt = (IStatement) p;
IRule rule = stt.getEnclosingRule();
if (!rules.contains(rule)) {
rules.add(rule);
}
}
return rules.toArray(new IRule[rules.size()]);
}
public static IModelElement[] collectPredicates(IGrammar grammar,
boolean ignorePredicatesInRewriteAlt) {
IModelElement[] elements = collectPredicates(grammar);
if (elements.length > 0 && ignorePredicatesInRewriteAlt) {
Collection<IModelElement> c = new ArrayList<IModelElement>(
elements.length);
for (IModelElement e : elements) {
if (!isInRewriteAlternative(e)) {
c.add(e);
}
}
if (elements.length != c.size()) {
elements = new IModelElement[c.size()];
elements = c.toArray(elements);
}
c.clear();
c = null;
}
return elements;
}
public static IModelElement[] collectPredicates(IRule rule) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.predicates());
collector.accept(rule);
IModelElement[] elements = collector.getResult();
return elements;
}
public static IModelElement[] findIgnoredRules(IGrammar grammar) {
AntlrModelElementCollectorVisitor collector = new AntlrModelElementCollectorVisitor(
ModelElementCriteriaFactory.ignoredRule());
collector.accept(grammar);
IModelElement[] elements = collector.getResult();
return elements;
}
}