All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.xtext.serializer.analysis.IGrammarConstraintProvider Maven / Gradle / Ivy

package org.eclipse.xtext.serializer.analysis;

import java.util.List;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.Action;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.Grammar;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.formallang.Production;

import com.google.inject.ImplementedBy;

/**
 * Based on an Xtext grammar, the IGrammarConstraintProvider provides constraints that the semantic model must comply
 * with. The structure of the constraints is as follows:
 * 
 * 
 * XtextGrammar 
 * \- 0..n IConstraintContext (one for each ParserRule and AssignedAction) 
 *    \- 1..n IConstraint (one for each EClass) 
 *       \- tree IConstraintElement (one for each relevant Group, Alternative, RuleCall and assigned Keyword)
 * 
* * @author Moritz Eysholdt - Initial contribution and API */ @ImplementedBy(GrammarConstraintProvider.class) public interface IGrammarConstraintProvider { /** * The ConstraintElementType distinguishes different kinds of {@link IConstraintElement} * * @see IConstraintElement#getType() */ public enum ConstraintElementType { ALTERNATIVE, // ASSIGNED_ACTION_CALL, // ASSIGNED_CROSSREF_DATATYPE_RULE_CALL, // ASSIGNED_CROSSREF_ENUM_RULE_CALL, // ASSIGNED_CROSSREF_TERMINAL_RULE_CALL, // ASSIGNED_CROSSREF_KEYWORD, // ASSIGNED_DATATYPE_RULE_CALL, // ASSIGNED_ENUM_RULE_CALL, // ASSIGNED_KEYWORD, // ASSIGNED_PARSER_RULE_CALL, // ASSIGNED_TERMINAL_RULE_CALL, // GROUP, } /** * One constraint defines all conditions one semantic object must comply with. A constraint is specific for one * EClass and belongs to one or more contexts. * * The conditions defined by a constraint are represented by a tree of {@link IConstraintElement}. This tree's root * can be accessed by {@link #getBody()}. */ public interface IConstraint extends Comparable { /** * @return a list of all assignments represented by this constraint. * {@link IConstraintElement#getAssignmentID()} returns an Assignment's index in this list. The order of * the list reflects the order of the assignments in the constraint. Assignments are * {@link IConstraintElement}s with {@link IConstraintElement#getType()} == ASSIGNED_* */ IConstraintElement[] getAssignments(); /** * @return the root of the tree of {@link IConstraintElement} that defines this constraint. */ IConstraintElement getBody(); /** * @return a list of all elements represented by this constraint. This is a flattened version of the tree * returned by {@link #getBody()}. {@link IConstraintElement#getElementID()} returns an Assignment's * index in this list. The order of the list reflects the order of the elements in the constraint. */ IConstraintElement[] getElements(); /** * @return a list of {@link IFeatureInfo} for all {@link EStructuralFeature}s from the {@link EClass} returned * by {@link #getType()} that have an assignment if this constraint. If there is no assignment for an * {@link EStructuralFeature} in this constraint, the array's item is null. */ IFeatureInfo[] getFeatures(); Iterable getSingleAssignementFeatures(); Iterable getMultiAssignementFeatures(); /** * @return a name that is unique for a grammar and that aims to be human-readable. */ String getName(); String getSimpleName(); /** * @return This constraint only applies to EObjects of this type. */ EClass getType(); } /** * A ConstraintContext is defined by a ParserRule or an AssignedAction. A ConstraintContext holds a list of all * constraints that are valid for this context. All these constraints have an EClass as their common super type. * * If the context is a parser rule, the constraints of this context describe all the objects that can be * instantiated via this parser rule. * * If this context is an assigned action, the constraints of this context describe all the objects that can assigned * by this action. These are all the objects that can be the "current" *before* the action is being executed. This * is *not* the EObject that is instantiated by the action. */ public interface IConstraintContext { // TODO: make sure this type is right for actions EClass getCommonType(); List getConstraints(); /** * @return an AssignedAction or ParserRule */ EObject getContext(); String getName(); } public class ConstraintElementProduction implements Production { protected IConstraint root; public ConstraintElementProduction(IConstraint root) { super(); this.root = root; } public Iterable getAlternativeChildren(IConstraintElement ele) { if (ele.getType() == ConstraintElementType.ALTERNATIVE) return ele.getChildren(); return null; } public Iterable getSequentialChildren(IConstraintElement ele) { if (ele.getType() == ConstraintElementType.GROUP) return ele.getChildren(); return null; } public AbstractElement getToken(IConstraintElement ele) { if (ele.getType() != ConstraintElementType.ALTERNATIVE && ele.getType() != ConstraintElementType.GROUP) return ele.getGrammarElement(); return null; } public Iterable getUnorderedChildren(IConstraintElement ele) { return null; } public boolean isMany(IConstraintElement ele) { return ele.isMany(); } public boolean isOptional(IConstraintElement ele) { return ele.isOptional(); } public IConstraintElement getParent(IConstraintElement ele) { return ele.getContainer(); } public IConstraintElement getRoot() { return root.getBody(); } } /** * IConstraintElements form a tree that is in fact a view on the grammar's AbstractElements. */ public interface IConstraintElement { // valid for *_ACTION_CALL Action getAction(); int getAssignmentID(); EObject getCallContext(); String getCardinality(); // valid for GROUP and ALTERNATIVE, null otherwise List getChildren(); IConstraintElement getContainer(); IConstraint getContainingConstraint(); // valid for *_CROSSREF_* CrossReference getCrossReference(); // valid for *_CROSSREF_* EClass getCrossReferenceType(); int getElementID(); // valid for ASSIGNED_* EStructuralFeature getFeature(); int getFeatureAssignmentID(); // valid for ASSIGNED_* IFeatureInfo getFeatureInfo(); // returns a RuleCall, Keyword or Action. But never an Assignment or // Cross Reference. AbstractElement getGrammarElement(); // valid for *_KEYWORD Keyword getKeyword(); // valid for *_RULE_CALL RuleCall getRuleCall(); ConstraintElementType getType(); List> getDependingAssignment(); List getContainedAssignments(); boolean isCardinalityOneAmongAssignments(List assignments); boolean isMany(); /** * @return true, if this element or one of its containers is isMany(). */ boolean isManyRecursive(IConstraintElement root); boolean isOptional(); boolean isRoot(); /** * @return true, if this element or one of its containers is optional. Also true, if one of the containers is an * alternative. */ boolean isOptionalRecursive(IConstraintElement root); } public interface IFeatureInfo { IConstraintElement[] getAssignments(); List getCalledContexts(); IConstraint getContainingConstraint(); EStructuralFeature getFeature(); /** * @return true for ASSIGNED_*, if there are multiple IConstraintELements for the same EStructuralFeature, which * refer to different keywords, rulecalls or cross references. */ boolean isContentValidationNeeded(); List> getDependingFeatures(); int getUpperBound(); int getLowerBound(); } public enum RelationalDependencyType { /** * (b >= 1) => (a == 0) */ EXCLUDE_IF_SET, /** * (b == 0) => (a == 0) */ EXCLUDE_IF_UNSET, /** * (b >= 1) => (a >= 0) */ MANDATORY_IF_SET, /** * a == b */ SAME, /** * a >= b */ SAME_OR_MORE, /** * a <= b */ SAME_OR_LESS } final int MAX = Integer.MAX_VALUE; /** * Returns all constraints form this grammar. If a constraint belongs to multiple ConstraintContexts, it is * important to call this method to ensure there is inly one instance fo this constraint. */ public List getConstraints(Grammar context); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy