mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
[serializer] implemented a fail-early strategy for sequencing
The backtracking algorithm of the semantic sequencer now avoids paths that can not lead to a successful consumption of all EOBject's values. To do so, every node of the state machine has knowledge about all EStructuralFeatures which its subsequent nodes refer to. If an EObject has unconsumed values within EStructuralFeatures that are not part of this list, the algorithm will not proceed past this node.
This commit is contained in:
parent
3ee879ab6d
commit
cc4beb3446
5 changed files with 284 additions and 125 deletions
|
@ -7,6 +7,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.serializer.analysis;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
|
@ -24,8 +25,10 @@ import com.google.inject.ImplementedBy;
|
|||
public interface ISemanticSequencerNfaProvider {
|
||||
|
||||
public interface ISemState {
|
||||
AbstractElement getAssignedGrammarElement();
|
||||
BitSet getAllFollowerFeatures();
|
||||
|
||||
AbstractElement getAssignedGrammarElement();
|
||||
|
||||
EStructuralFeature getFeature();
|
||||
|
||||
int getFeatureID();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.serializer.analysis;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
@ -36,6 +37,7 @@ import com.google.common.collect.HashMultimap;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
|
@ -56,10 +58,6 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
this.stop = stops;
|
||||
}
|
||||
|
||||
public ISemState getStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
public List<ISemState> getFollowers(ISemState node) {
|
||||
return node.getFollowers();
|
||||
}
|
||||
|
@ -68,16 +66,21 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
return start;
|
||||
}
|
||||
|
||||
public ISemState getStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class SemState implements ISemState {
|
||||
|
||||
protected AbstractElement assignedGrammarElement;
|
||||
protected EStructuralFeature feature;
|
||||
protected int featureID = -1;
|
||||
protected int featureID = -2;
|
||||
protected List<ISemState> followers;
|
||||
protected EClass type;
|
||||
protected List<AbstractElement> contentValidationNeeded;
|
||||
protected BitSet allFollowerFeatures;
|
||||
|
||||
public SemState(EClass type, AbstractElement assignedGrammarElement) {
|
||||
super();
|
||||
|
@ -85,6 +88,12 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
this.assignedGrammarElement = assignedGrammarElement;
|
||||
}
|
||||
|
||||
public BitSet getAllFollowerFeatures() {
|
||||
if (allFollowerFeatures == null)
|
||||
allFollowerFeatures = new BitSet();
|
||||
return allFollowerFeatures;
|
||||
}
|
||||
|
||||
public AbstractElement getAssignedGrammarElement() {
|
||||
return assignedGrammarElement;
|
||||
}
|
||||
|
@ -96,8 +105,8 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
}
|
||||
|
||||
public int getFeatureID() {
|
||||
if (featureID < 0)
|
||||
featureID = type.getFeatureID(getFeature());
|
||||
if (featureID < -1)
|
||||
featureID = getFeature() != null ? type.getFeatureID(getFeature()) : -1;
|
||||
return featureID;
|
||||
}
|
||||
|
||||
|
@ -152,11 +161,53 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
nfa = util.create(util.sort(synNfa, distanceMap), new SemStateFactory());
|
||||
// util.sortInplace(nfa, distanceMap);
|
||||
initContentValidationNeeded(type, nfa);
|
||||
initRemainingFeatures(nfa.getStop(), util.inverse(nfa), Sets.<ISemState> newHashSet());
|
||||
// System.out.println(new NfaFormatter().format(nfa));
|
||||
cache.put(key, nfa);
|
||||
return nfa;
|
||||
}
|
||||
|
||||
protected void initContentValidationNeeded(EClass clazz, Nfa<ISemState> nfa) {
|
||||
Multimap<EStructuralFeature, AbstractElement> assignments = HashMultimap.create();
|
||||
Set<ISemState> states = new NfaUtil().collect(nfa);
|
||||
for (ISemState state : states)
|
||||
if (state.getFeature() != null)
|
||||
assignments.put(state.getFeature(), state.getAssignedGrammarElement());
|
||||
boolean[] validationNeeded = new boolean[clazz.getFeatureCount()];
|
||||
for (EStructuralFeature feature : clazz.getEAllStructuralFeatures())
|
||||
validationNeeded[clazz.getFeatureID(feature)] = isContentValidationNeeded(assignments.get(feature));
|
||||
for (ISemState state : states)
|
||||
if (state.getFeature() != null && validationNeeded[state.getFeatureID()])
|
||||
((SemState) state).contentValidationNeeded = Lists.newArrayList(assignments.get(state.getFeature()));
|
||||
else
|
||||
((SemState) state).contentValidationNeeded = Collections.emptyList();
|
||||
}
|
||||
|
||||
protected void initRemainingFeatures(ISemState state, Nfa<ISemState> inverseNfa, Set<ISemState> visited) {
|
||||
BitSet features = state.getAllFollowerFeatures();
|
||||
if (state.getFeature() != null) {
|
||||
BitSet f = new BitSet();
|
||||
f.or(features);
|
||||
f.set(state.getFeatureID());
|
||||
features = f;
|
||||
}
|
||||
for (ISemState follower : inverseNfa.getFollowers(state)) {
|
||||
if (!addAll(follower.getAllFollowerFeatures(), features) && !visited.add(follower))
|
||||
continue;
|
||||
initRemainingFeatures(follower, inverseNfa, visited);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean addAll(BitSet to, BitSet bits) {
|
||||
BitSet cpy = new BitSet();
|
||||
cpy.or(to);
|
||||
cpy.or(bits);
|
||||
if (cpy.equals(to))
|
||||
return false;
|
||||
to.or(bits);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isContentValidationNeeded(Collection<AbstractElement> ass) {
|
||||
if (ass == null || ass.size() < 2)
|
||||
return false;
|
||||
|
@ -177,20 +228,4 @@ public class SemanticSequencerNfaProvider implements ISemanticSequencerNfaProvid
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void initContentValidationNeeded(EClass clazz, Nfa<ISemState> nfa) {
|
||||
Multimap<EStructuralFeature, AbstractElement> assignments = HashMultimap.create();
|
||||
Set<ISemState> states = new NfaUtil().collect(nfa);
|
||||
for (ISemState state : states)
|
||||
if (state.getFeature() != null)
|
||||
assignments.put(state.getFeature(), state.getAssignedGrammarElement());
|
||||
boolean[] validationNeeded = new boolean[clazz.getFeatureCount()];
|
||||
for (EStructuralFeature feature : clazz.getEAllStructuralFeatures())
|
||||
validationNeeded[clazz.getFeatureID(feature)] = isContentValidationNeeded(assignments.get(feature));
|
||||
for (ISemState state : states)
|
||||
if (state.getFeature() != null && validationNeeded[state.getFeatureID()])
|
||||
((SemState) state).contentValidationNeeded = Lists.newArrayList(assignments.get(state.getFeature()));
|
||||
else
|
||||
((SemState) state).contentValidationNeeded = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.xtext.nodemodel.ICompositeNode;
|
|||
import org.eclipse.xtext.nodemodel.ILeafNode;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
|
||||
import org.eclipse.xtext.serializer.analysis.Context2NameFunction;
|
||||
import org.eclipse.xtext.serializer.analysis.ISemanticSequencerNfaProvider;
|
||||
import org.eclipse.xtext.serializer.analysis.ISemanticSequencerNfaProvider.ISemState;
|
||||
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
|
||||
|
@ -74,11 +75,15 @@ public class BacktrackingSemanticSequencer extends AbstractSemanticSequencer {
|
|||
return 1;
|
||||
boolean o1Opt = obj.isOptional(o1.getFeatureID());
|
||||
boolean o2Opt = obj.isOptional(o2.getFeatureID());
|
||||
if (o1Opt && o2Opt)
|
||||
return 0;
|
||||
if (o1Opt)
|
||||
if (o1Opt && !o2Opt)
|
||||
return 1;
|
||||
if (o2Opt)
|
||||
if (o2Opt && !o1Opt)
|
||||
return -1;
|
||||
int o1Cnt = obj.getValueCount(o1.getFeatureID());
|
||||
int o2Cnt = obj.getValueCount(o2.getFeatureID());
|
||||
if (o1Cnt == 0 && o2Cnt > 0)
|
||||
return 1;
|
||||
if (o2Cnt == 0 && o1Cnt > 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -283,6 +288,20 @@ public class BacktrackingSemanticSequencer extends AbstractSemanticSequencer {
|
|||
return result;
|
||||
}
|
||||
|
||||
public boolean canEnter(ISemState state) {
|
||||
for (int i = 0; i < nextIndex.length; i++)
|
||||
if (i != state.getFeatureID()) {
|
||||
int count = nextIndex[i];
|
||||
if (count < obj.getValueCount(i)) {
|
||||
if (count == 0 && obj.isOptional(i))
|
||||
continue;
|
||||
if (!state.getAllFollowerFeatures().get(i))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
@ -349,6 +368,7 @@ public class BacktrackingSemanticSequencer extends AbstractSemanticSequencer {
|
|||
consumed.add(feature.getName() + "(" + count + ")");
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("State: " + state + "\n");
|
||||
result.append("EObject: " + EmfFormatter.objPath(obj.getEObject()) + "\n");
|
||||
result.append("Remaining Mandatory Values: " + Joiner.on(", ").join(mandatory) + "\n");
|
||||
result.append("Remaining Optional Values: " + Joiner.on(", ").join(optional) + "\n");
|
||||
|
@ -399,6 +419,8 @@ public class BacktrackingSemanticSequencer extends AbstractSemanticSequencer {
|
|||
TraceItem co = new TraceItem(object);
|
||||
List<TraceItem> trace = new NfaUtil().backtrack(nfa, co, new NfaUtil.BacktrackHandler<ISemState, TraceItem>() {
|
||||
public TraceItem handle(ISemState state, TraceItem previous) {
|
||||
if (!previous.canEnter(state))
|
||||
return null;
|
||||
if (state.getFeature() != null) {
|
||||
return previous.cloneAndConsume(state);
|
||||
} else
|
||||
|
|
|
@ -83,173 +83,211 @@ public abstract class AbstractSemanticSequencerTest extends AbstractXtextTests {
|
|||
@Test
|
||||
@Ignore
|
||||
public void testXtext() throws Exception {
|
||||
// with(XtextStandaloneSetup.class);
|
||||
// EObject model = getGrammarAccess().getGrammar();
|
||||
// // System.out.println(EmfFormatter.objToStr(model));
|
||||
// EObject ctx = GrammarUtil.findRuleForName(getGrammarAccess().getGrammar(), "AbstractToken");
|
||||
// // ISemanticSequencer semSequencer = get(ISemanticSequencer.class);
|
||||
// // EObject ctx = semSequencer.findContexts(model, null).iterator().next();
|
||||
// ISyntacticSequencer synSeq = get(PassThroughSyntacticSequencer.class);
|
||||
// IHiddenTokenSequencer hiddenSeq = get(PassThroughHiddenTokenSequencer.class);
|
||||
// IRecursiveSequencer recSequencer = get(IRecursiveSequencer.class);
|
||||
// ((IHiddenTokenSequencerOwner) recSequencer).setHiddenTokenSequencer(hiddenSeq);
|
||||
// ((ISyntacticSequencerOwner) hiddenSeq).setSyntacticSequencer(synSeq);
|
||||
// DebugSequenceAcceptor actual = new DebugSequenceAcceptor();
|
||||
// recSequencer.createSequence( /* semSequencer, */ctx, model, actual, ISerializationDiagnostic.STDERR_ACCEPTOR);
|
||||
// // String actual = sequenceRecursively(semSequencer, ctx, model, true);
|
||||
// // System.out.println(actual);
|
||||
// assertNotNull(actual);
|
||||
// with(XtextStandaloneSetup.class);
|
||||
// EObject model = getGrammarAccess().getGrammar();
|
||||
// // System.out.println(EmfFormatter.objToStr(model));
|
||||
// EObject ctx = GrammarUtil.findRuleForName(getGrammarAccess().getGrammar(), "AbstractToken");
|
||||
// // ISemanticSequencer semSequencer = get(ISemanticSequencer.class);
|
||||
// // EObject ctx = semSequencer.findContexts(model, null).iterator().next();
|
||||
// ISyntacticSequencer synSeq = get(PassThroughSyntacticSequencer.class);
|
||||
// IHiddenTokenSequencer hiddenSeq = get(PassThroughHiddenTokenSequencer.class);
|
||||
// IRecursiveSequencer recSequencer = get(IRecursiveSequencer.class);
|
||||
// ((IHiddenTokenSequencerOwner) recSequencer).setHiddenTokenSequencer(hiddenSeq);
|
||||
// ((ISyntacticSequencerOwner) hiddenSeq).setSyntacticSequencer(synSeq);
|
||||
// DebugSequenceAcceptor actual = new DebugSequenceAcceptor();
|
||||
// recSequencer.createSequence( /* semSequencer, */ctx, model, actual, ISerializationDiagnostic.STDERR_ACCEPTOR);
|
||||
// // String actual = sequenceRecursively(semSequencer, ctx, model, true);
|
||||
// // System.out.println(actual);
|
||||
// assertNotNull(actual);
|
||||
}
|
||||
|
||||
@Test public void testSimpleGroup() throws Exception {
|
||||
@Test
|
||||
public void testSimpleGroup() throws Exception {
|
||||
testSequence("#1 a b");
|
||||
}
|
||||
|
||||
@Test public void testSimpleAlternative1() throws Exception {
|
||||
@Test
|
||||
public void testSimpleAlternative1() throws Exception {
|
||||
testSequence("#2 kw2 a");
|
||||
}
|
||||
|
||||
@Test public void testSimpleAlternative2() throws Exception {
|
||||
@Test
|
||||
public void testSimpleAlternative2() throws Exception {
|
||||
testSequence("#2 kw2 a");
|
||||
}
|
||||
|
||||
@Test public void testSimpleMultiplicities1() throws Exception {
|
||||
@Test
|
||||
public void testSimpleMultiplicities1() throws Exception {
|
||||
testSequence("#3 a kw1 b kw2 c d kw3 e f");
|
||||
}
|
||||
|
||||
@Test public void testSimpleMultiplicities2() throws Exception {
|
||||
@Test
|
||||
public void testSimpleMultiplicities2() throws Exception {
|
||||
testSequence("#3 a kw1 kw2 c kw3 e");
|
||||
}
|
||||
|
||||
@Test public void testSimpleMultiplicities3() throws Exception {
|
||||
@Test
|
||||
public void testSimpleMultiplicities3() throws Exception {
|
||||
testSequence("#3 a kw1 kw2 c kw3");
|
||||
}
|
||||
|
||||
@Test public void testGroupMultiplicities1() throws Exception {
|
||||
@Test
|
||||
public void testGroupMultiplicities1() throws Exception {
|
||||
testSequence("#4 a kw1 b c kw2 d e f g kw3 h i j k");
|
||||
}
|
||||
|
||||
@Test public void testGroupMultiplicities2() throws Exception {
|
||||
@Test
|
||||
public void testGroupMultiplicities2() throws Exception {
|
||||
testSequence("#4 a kw1 b c kw2 d e kw3 h i");
|
||||
}
|
||||
|
||||
@Test public void testGroupMultiplicities3() throws Exception {
|
||||
@Test
|
||||
public void testGroupMultiplicities3() throws Exception {
|
||||
testSequence("#4 a kw1 b c kw2 d e kw3");
|
||||
}
|
||||
|
||||
@Test public void testAlternativeMultiplicities1() throws Exception {
|
||||
@Test
|
||||
public void testAlternativeMultiplicities1() throws Exception {
|
||||
testSequence("#5 a kw2 b c kw3 d kw3 e kw4 g h kw5 i kw5 j");
|
||||
}
|
||||
|
||||
@Test public void testAlternativeMultiplicities2() throws Exception {
|
||||
@Test
|
||||
public void testAlternativeMultiplicities2() throws Exception {
|
||||
testSequence("#5 kw1 a kw2 b kw4 g");
|
||||
}
|
||||
|
||||
@Test public void testAlternativeMultiplicities3() throws Exception {
|
||||
@Test
|
||||
public void testAlternativeMultiplicities3() throws Exception {
|
||||
testSequence("#5 kw1 a kw2 kw3 b kw4 kw5 g");
|
||||
}
|
||||
|
||||
@Test public void testAlternativeMultiplicities4() throws Exception {
|
||||
@Test
|
||||
public void testAlternativeMultiplicities4() throws Exception {
|
||||
testSequence("#5 kw1 a kw2 kw3 b kw4");
|
||||
}
|
||||
|
||||
@Test public void testList1a() throws Exception {
|
||||
@Test
|
||||
public void testList1a() throws Exception {
|
||||
testSequence("#6 a, b, c, d, e");
|
||||
}
|
||||
|
||||
@Test public void testList1b() throws Exception {
|
||||
@Test
|
||||
public void testList1b() throws Exception {
|
||||
testSequence("#6 a, b");
|
||||
}
|
||||
|
||||
@Test public void testList1c() throws Exception {
|
||||
@Test
|
||||
public void testList1c() throws Exception {
|
||||
testSequence("#6 a");
|
||||
}
|
||||
|
||||
@Test public void testList2a() throws Exception {
|
||||
@Test
|
||||
public void testList2a() throws Exception {
|
||||
testSequence("#7 a, b, c");
|
||||
}
|
||||
|
||||
@Test public void testList2b() throws Exception {
|
||||
@Test
|
||||
public void testList2b() throws Exception {
|
||||
testSequence("#7 a, b");
|
||||
}
|
||||
|
||||
@Test public void testList2c() throws Exception {
|
||||
@Test
|
||||
public void testList2c() throws Exception {
|
||||
testSequence("#7 a");
|
||||
}
|
||||
|
||||
@Test public void testList2d() throws Exception {
|
||||
@Test
|
||||
public void testList2d() throws Exception {
|
||||
testSequence("#7");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeyword1() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeyword1() throws Exception {
|
||||
testSequence("#10 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeyword2() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeyword2() throws Exception {
|
||||
testSequence("#10 kw2");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeyword3() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeyword3() throws Exception {
|
||||
testSequence("#10 kw3");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeyword1OrID() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeyword1OrID() throws Exception {
|
||||
testSequence("#11 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeywordOrID2() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeywordOrID2() throws Exception {
|
||||
testSequence("#11 kw2");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeywordOrID3() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeywordOrID3() throws Exception {
|
||||
testSequence("#11 kw3");
|
||||
}
|
||||
|
||||
@Test public void testSingleKeywordOrID4() throws Exception {
|
||||
@Test
|
||||
public void testSingleKeywordOrID4() throws Exception {
|
||||
testSequence("#11 foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleTerminals1() throws Exception {
|
||||
@Test
|
||||
public void testSingleTerminals1() throws Exception {
|
||||
testSequence("#12 $1foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleTerminals2() throws Exception {
|
||||
@Test
|
||||
public void testSingleTerminals2() throws Exception {
|
||||
testSequence("#12 $2foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleEnum1() throws Exception {
|
||||
@Test
|
||||
public void testSingleEnum1() throws Exception {
|
||||
testSequence("#13 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleEnum2() throws Exception {
|
||||
@Test
|
||||
public void testSingleEnum2() throws Exception {
|
||||
testSequence("#13 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleEnum3() throws Exception {
|
||||
@Test
|
||||
public void testSingleEnum3() throws Exception {
|
||||
testSequence("#13 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleCrossReference1() throws Exception {
|
||||
@Test
|
||||
public void testSingleCrossReference1() throws Exception {
|
||||
testSequence("#14 $1foo $1foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleCrossReference2() throws Exception {
|
||||
@Test
|
||||
public void testSingleCrossReference2() throws Exception {
|
||||
testSequence("#14 $2foo $2foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleCrossReference3() throws Exception {
|
||||
@Test
|
||||
public void testSingleCrossReference3() throws Exception {
|
||||
testSequence("#14 $3foo $3foo");
|
||||
}
|
||||
|
||||
@Test public void testSingleContainmentReference1() throws Exception {
|
||||
@Test
|
||||
public void testSingleContainmentReference1() throws Exception {
|
||||
testSequence("#15 kw1");
|
||||
}
|
||||
|
||||
@Test public void testSingleContainmentReference2() throws Exception {
|
||||
@Test
|
||||
public void testSingleContainmentReference2() throws Exception {
|
||||
testSequence("#15 kw2");
|
||||
}
|
||||
|
||||
@Test public void testSingleContainmentReference3() throws Exception {
|
||||
@Test
|
||||
public void testSingleContainmentReference3() throws Exception {
|
||||
testSequence("#15 kw3");
|
||||
}
|
||||
|
||||
|
@ -271,168 +309,225 @@ public abstract class AbstractSemanticSequencerTest extends AbstractXtextTests {
|
|||
testSequence("#8 kw3 a");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative1_a() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative1_a() throws Exception {
|
||||
testSequence("#19 foo1");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative1_b() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative1_b() throws Exception {
|
||||
testSequence("#19 foo kw1");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative2_a() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative2_a() throws Exception {
|
||||
testSequence("#20 foo bar");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative2_b() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative2_b() throws Exception {
|
||||
testSequence("#20 foo bar baz");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative2_c() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative2_c() throws Exception {
|
||||
testSequence("#20 foo bar kw1");
|
||||
}
|
||||
|
||||
@Test public void testDependentAlternative2_d() throws Exception {
|
||||
@Test
|
||||
public void testDependentAlternative2_d() throws Exception {
|
||||
testSequence("#20 foo kw1");
|
||||
}
|
||||
|
||||
@Test public void testOptional1_a() throws Exception {
|
||||
@Test
|
||||
public void testOptional1_a() throws Exception {
|
||||
testSequence("#21 1 2 3");
|
||||
}
|
||||
|
||||
@Test public void testOptional1_b() throws Exception {
|
||||
@Test
|
||||
public void testOptional1_b() throws Exception {
|
||||
testSequence("#21 0 0 1");
|
||||
}
|
||||
|
||||
@Test public void testOptional1_c() throws Exception {
|
||||
@Test
|
||||
public void testOptional1_c() throws Exception {
|
||||
testSequence("#21 0 0 0");
|
||||
}
|
||||
|
||||
@Test public void testOptional1_d() throws Exception {
|
||||
@Test
|
||||
public void testOptional1_d() throws Exception {
|
||||
testSequence("#21 0");
|
||||
}
|
||||
|
||||
@Test public void testOptional1_e() throws Exception {
|
||||
@Test
|
||||
public void testOptional1_e() throws Exception {
|
||||
testSequence("#21 1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative1() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative1() throws Exception {
|
||||
testSequence("#23 1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative2() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative2() throws Exception {
|
||||
testSequence("#23 a 1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative3() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative3() throws Exception {
|
||||
testSequence("#23 kw1 a kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative4() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative4() throws Exception {
|
||||
testSequence("#23 kw2 b kw1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative5() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative5() throws Exception {
|
||||
testSequence("#23 1 a kw1 a kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative6() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative6() throws Exception {
|
||||
testSequence("#23 kw2 b kw1 a a 1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedAlternative7() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedAlternative7() throws Exception {
|
||||
testSequence("#23 kw2 b kw1 a a 1 c d 2 i 7 kw2 x kw1 x 8 g");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup1() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup1() throws Exception {
|
||||
testSequence("#24 1 a kw1 a kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup2() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup2() throws Exception {
|
||||
testSequence("#24 1 a kw2 b kw1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup3() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup3() throws Exception {
|
||||
testSequence("#24 a 1 kw1 a kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup4() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup4() throws Exception {
|
||||
testSequence("#24 a 1 kw2 b kw1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup5() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup5() throws Exception {
|
||||
testSequence("#24 kw1 a kw2 b 1 a ");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup6() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup6() throws Exception {
|
||||
testSequence("#24 kw2 b kw1 a 1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup7() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup7() throws Exception {
|
||||
testSequence("#24 kw1 a kw2 b a 1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroup8() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroup8() throws Exception {
|
||||
testSequence("#24 kw2 b kw1 a a 1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional1() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional1() throws Exception {
|
||||
testSequence("#25 kw1 a kw2 b kw3 c");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional2() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional2() throws Exception {
|
||||
testSequence("#25 kw1 a kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional3() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional3() throws Exception {
|
||||
testSequence("#25 kw1 a kw3 c");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional4() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional4() throws Exception {
|
||||
testSequence("#25 kw2 b kw3 c");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional5() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional5() throws Exception {
|
||||
testSequence("#25 kw2 b kw1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional6() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional6() throws Exception {
|
||||
testSequence("#25 kw3 c kw1 a");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupOptional7() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupOptional7() throws Exception {
|
||||
testSequence("#25 kw3 c kw2 b");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean1() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean1() throws Exception {
|
||||
testSequence("#26 kw1 kw2");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean2() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean2() throws Exception {
|
||||
testSequence("#26 kw2 kw1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean3() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean3() throws Exception {
|
||||
testSequence("#26 kw2 kw3");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean4() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean4() throws Exception {
|
||||
testSequence("#26 kw3 kw2");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean5() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean5() throws Exception {
|
||||
testSequence("#26 kw1 kw3");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean6() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean6() throws Exception {
|
||||
testSequence("#26 kw3 kw1");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean7() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean7() throws Exception {
|
||||
testSequence("#26 kw1 kw2 kw3");
|
||||
}
|
||||
|
||||
@Test public void testUnorderedGroupBoolean8() throws Exception {
|
||||
@Test
|
||||
public void testUnorderedGroupBoolean8() throws Exception {
|
||||
testSequence("#26 kw3 kw2 kw1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex1a() throws Exception {
|
||||
testSequence("#27 kw1 v1 kw2 v2 kw3 v3 kw4 v4 kw5 v5 kw6 v6");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex1b() throws Exception {
|
||||
testSequence("#27 kw6 v6");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplex1c() throws Exception {
|
||||
testSequence("#27 kw3 v3 kw4 v4 kw5 v5 kw6 v6");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@ Model:
|
|||
x13=SingleEnum | x14=SingleCrossReference | x15=SingleContainmentReference |
|
||||
x19=DependentAlternative1 | x20=DependentAlternative2 | x21=Optional | x22=Float |
|
||||
x23=UnorderedAlternative | x24=UnorderedGroup | x25=UnorderedGroupOptional |
|
||||
x26=UnorderedGroupBoolean;
|
||||
x26=UnorderedGroupBoolean | x27=Complex1;
|
||||
|
||||
SimpleGroup:
|
||||
"#1" val1=ID val2=ID;
|
||||
|
@ -142,4 +142,8 @@ UnorderedGroupOptional:
|
|||
"#25" {UnorderedGroupOptional} (("kw1" val1=ID)? & ("kw2" va2=ID)? & ("kw3" val3=ID)?);
|
||||
|
||||
UnorderedGroupBoolean:
|
||||
'#26' {UnorderedGroupBoolean} (val1?='kw1'? & val2?='kw2'? & val3?='kw3'?);
|
||||
'#26' {UnorderedGroupBoolean} (val1?='kw1'? & val2?='kw2'? & val3?='kw3'?);
|
||||
|
||||
Complex1:
|
||||
'#27' {Complex1} ("kw1" val1=ID)? ("kw2" val2=ID)? (("kw3" val3+=ID) | ("kw4" val4+=ID) | ("kw5" val5+=ID) | ("kw6" val6+=ID))*;
|
||||
|
Loading…
Reference in a new issue