/* * $Id$ * * SARL is an general-purpose agent programming language. * More details on http://www.sarl.io * * Copyright (C) 2014-2017 the original authors or authors. * * Licensed 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 io.sarl.lang.mwe2.codebuilder.extractor; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.inject.Singleton; import com.google.common.collect.Iterables; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Action; import org.eclipse.xtext.Assignment; import org.eclipse.xtext.Grammar; import org.eclipse.xtext.GrammarUtil; import org.eclipse.xtext.Group; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.xbase.lib.Functions.Function4; import org.eclipse.xtext.xbase.lib.IterableExtensions; import io.sarl.lang.mwe2.codebuilder.config.CodeBuilderConfig; /** Extract elements from the no-bracktracking grammar. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ @Singleton public class NoBacktrackGrammarCodeElementExtractor extends AbstractCodeElementExtractor { @Override public Iterable<ElementDescription> getTopElements(Grammar grammar, CodeBuilderConfig config) { final AbstractRule topRule = GrammarUtil.findRuleForName(grammar, config.getTopElementRuleName()); if (topRule != null) { final EClassifier commonType = getGeneratedTypeFor(topRule); final Iterable<Action> filteredElements = Iterables.filter(GrammarUtil.containedActions(topRule), (it) -> !Strings.isEmpty(it.getFeature())); return Iterables.transform(filteredElements, (it) -> { final EClassifier classifier = it.getType().getClassifier(); final String name = classifier.getName(); final Group container = GrammarUtil.containingGroup(it); return newElementDescription(name, container, classifier, commonType); }); } return Collections.emptyList(); } private <T> T visitMembers(EObject grammarContainer, EObject container, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> memberCallback) { final Set<String> treatedMembers = new HashSet<>(); for (final Assignment nameAssignment : IterableExtensions.filter( GrammarUtil.containedAssignments(container), (passignment) -> getCodeBuilderConfig() .getMemberNameExtensionGrammarName().equals(passignment.getFeature()))) { // Get the container of the name assignment final EObject assignmentContainer = getContainerInRule(grammarContainer, nameAssignment); if (assignmentContainer != null) { final EClassifier classifier = getGeneratedTypeFor(assignmentContainer); if (!treatedMembers.contains(classifier.getName())) { treatedMembers.add(classifier.getName()); final T retVal = memberCallback.apply(this, grammarContainer, assignmentContainer, classifier); if (retVal != null) { return retVal; } } } } return null; } private <T> T visitTypeReferencingMembers(EObject grammarContainer, EObject container, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> memberCallback) { final Set<String> treatedMembers = new HashSet<>(); for (final Assignment nameAssignment : IterableExtensions.filter( GrammarUtil.containedAssignments(container), (passignment) -> getCodeBuilderConfig() .getUnnamedMemberExtensionGrammarNames().contains(passignment.getFeature()))) { // Get the container of the name assignment final EObject assignmentContainer = getContainerInRule(grammarContainer, nameAssignment); if (assignmentContainer != null) { final EClassifier classifier = getGeneratedTypeFor(assignmentContainer); if (!treatedMembers.contains(classifier.getName())) { treatedMembers.add(classifier.getName()); final T retVal = memberCallback.apply(this, grammarContainer, assignmentContainer, classifier); if (retVal != null) { return retVal; } } } } return null; } private <T> T visitConstructors(EObject grammarContainer, EObject container, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> callback) { final Set<String> treatedConstructors = new HashSet<>(); for (final Assignment expressionAssignment : IterableExtensions.filter( GrammarUtil.containedAssignments(container), (passignment) -> getCodeBuilderConfig() .getMemberBlockExpressionExtensionGrammarName().equals(passignment.getFeature()))) { // Get the container of the name assignment final EObject consContainer = getContainerInRule(grammarContainer, expressionAssignment); if (consContainer != null && !IterableExtensions.exists(GrammarUtil.containedAssignments(consContainer), (it) -> getCodeBuilderConfig() .getMemberNameExtensionGrammarName().equals(it.getFeature()))) { final EClassifier classifier = getGeneratedTypeFor(consContainer); if (!treatedConstructors.contains(classifier.getName())) { treatedConstructors.add(classifier.getName()); final T retVal = callback.apply(this, grammarContainer, consContainer, classifier); if (retVal != null) { return retVal; } } } } return null; } @Override public <T> T visitMemberElements( ElementDescription element, EObject grammarContainer, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> constructorCallback, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> namedMemberCallback, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> typeReferencingMemberCallback) { // Treat the standard members if (namedMemberCallback != null) { final T retVal = visitMembers(grammarContainer, grammarContainer, namedMemberCallback); if (retVal != null) { return retVal; } } // Treat the members that are referencing types. if (typeReferencingMemberCallback != null) { final T retVal = visitTypeReferencingMembers(grammarContainer, grammarContainer, typeReferencingMemberCallback); if (retVal != null) { return retVal; } } // Treat the constructors if (constructorCallback != null && !getCodeBuilderConfig().getConstructorFreeTypes().contains(element.getName())) { final T retVal = visitConstructors(grammarContainer, grammarContainer, constructorCallback); if (retVal != null) { return retVal; } } return null; } }