mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
fixed bug with alternatives containing unordered groups
gave exception in token analysis -> added handling for unordered groups to token analysis added test case
This commit is contained in:
parent
13aef9e99b
commit
83232e5a43
3 changed files with 42 additions and 5 deletions
|
@ -579,6 +579,24 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
||||||
assertTrue(guard.hasTerminal());
|
assertTrue(guard.hasTerminal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnorderedGroupInAlternatives_bugUnknownElementInTokenAnalysis_expectNoException() throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
String model =
|
||||||
|
MODEL_PREAMBLE +
|
||||||
|
"S: {S} $$ p0 $$?=> 'a' \n" +
|
||||||
|
" | {S} $$ p1 $$?=> ('b' & 'c');";
|
||||||
|
// @formatter:off
|
||||||
|
XtextResource resource = getResourceFromString(model);
|
||||||
|
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||||
|
AbstractRule rule = getRule(grammar, "S");
|
||||||
|
|
||||||
|
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||||
|
assertFalse(guard.isTrivial());
|
||||||
|
assertTrue(guard.hasTerminal());
|
||||||
|
assertEquals("((" + getSyntaxForKeywordToken("a", 1) + " || (p0)) && ((" + getSyntaxForKeywordToken("b", 1) + " && " + getSyntaxForKeywordToken("c", 1) + ") || (p1)))", guard.render());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAlternativeUnguardedPath() throws Exception {
|
public void testAlternativeUnguardedPath() throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
|
|
@ -25,12 +25,16 @@ import org.eclipse.xtext.AbstractSemanticPredicate;
|
||||||
import org.eclipse.xtext.Action;
|
import org.eclipse.xtext.Action;
|
||||||
import org.eclipse.xtext.Alternatives;
|
import org.eclipse.xtext.Alternatives;
|
||||||
import org.eclipse.xtext.Assignment;
|
import org.eclipse.xtext.Assignment;
|
||||||
|
import org.eclipse.xtext.CompoundElement;
|
||||||
|
import org.eclipse.xtext.GrammarUtil;
|
||||||
import org.eclipse.xtext.Group;
|
import org.eclipse.xtext.Group;
|
||||||
import org.eclipse.xtext.JavaAction;
|
import org.eclipse.xtext.JavaAction;
|
||||||
import org.eclipse.xtext.RuleCall;
|
import org.eclipse.xtext.RuleCall;
|
||||||
|
import org.eclipse.xtext.UnorderedGroup;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.HoistingConfiguration;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.HoistingConfiguration;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.SymbolicAnalysisFailedException;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.SymbolicAnalysisFailedException;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.TokenAnalysisAbortedException;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.TokenAnalysisAbortedException;
|
||||||
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.UnsupportedConstructException;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.token.Token;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.token.Token;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.MutablePrimitiveWrapper;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.MutablePrimitiveWrapper;
|
||||||
|
|
||||||
|
@ -48,7 +52,7 @@ public class TokenAnalysis {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TokenAnalysisPaths getTokenForIndexesAlternatives(Alternatives path, TokenAnalysisPaths prefix, boolean needsLength) throws TokenAnalysisAbortedException {
|
private TokenAnalysisPaths getTokenForIndexesAlternatives(CompoundElement path, TokenAnalysisPaths prefix, boolean needsLength) throws TokenAnalysisAbortedException {
|
||||||
if (prefix.isDone()) {
|
if (prefix.isDone()) {
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +169,7 @@ public class TokenAnalysis {
|
||||||
} else if (path instanceof Assignment) {
|
} else if (path instanceof Assignment) {
|
||||||
current = getTokenForIndexes(((Assignment) path).getTerminal(), current, false);
|
current = getTokenForIndexes(((Assignment) path).getTerminal(), current, false);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("unknown element: " + path.eClass().getName());
|
throw new UnsupportedConstructException("unknown element: " + path.eClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// add path to result
|
// add path to result
|
||||||
|
@ -192,6 +196,23 @@ public class TokenAnalysis {
|
||||||
return getTokenForIndexesAlternatives((Alternatives) path, prefix, needsLength);
|
return getTokenForIndexesAlternatives((Alternatives) path, prefix, needsLength);
|
||||||
} else if (path instanceof Group) {
|
} else if (path instanceof Group) {
|
||||||
return getTokenForIndexesGroup((Group) path, prefix, needsLength);
|
return getTokenForIndexesGroup((Group) path, prefix, needsLength);
|
||||||
|
} else if (path instanceof UnorderedGroup) {
|
||||||
|
// clone unordered group
|
||||||
|
// set cardinality accordingly
|
||||||
|
// use code for alternatives
|
||||||
|
|
||||||
|
CompoundElement clonedUnorderedGroup = (CompoundElement) cloneAbstractElement(path);
|
||||||
|
if (isOptionalCardinality(path) ||
|
||||||
|
((UnorderedGroup) path).getElements().stream().allMatch(GrammarUtil::isOptionalCardinality)
|
||||||
|
){
|
||||||
|
clonedUnorderedGroup.setCardinality("*");
|
||||||
|
} else {
|
||||||
|
clonedUnorderedGroup.setCardinality("+");
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTokenForIndexesAlternatives only needs a CompoundElement so we can give it
|
||||||
|
// the modified unordered group
|
||||||
|
return getTokenForIndexesAlternatives(clonedUnorderedGroup, prefix, needsLength);
|
||||||
} else if (path instanceof Action ||
|
} else if (path instanceof Action ||
|
||||||
path instanceof AbstractSemanticPredicate ||
|
path instanceof AbstractSemanticPredicate ||
|
||||||
path instanceof JavaAction
|
path instanceof JavaAction
|
||||||
|
@ -217,7 +238,7 @@ public class TokenAnalysis {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean arePathsIdenticalFallback(AbstractElement path1, AbstractElement path2) {
|
private boolean arePathsIdenticalFallback(AbstractElement path1, AbstractElement path2) {
|
||||||
// + 1, because otherwise identical paths of length TOKEN_ANALYSIS_LIMIT can't be checked
|
// + 1, because otherwise identical paths of length token limit can't be checked
|
||||||
for (int i = 0; i < config.getTokenLimit() + 1; i++) {
|
for (int i = 0; i < config.getTokenLimit() + 1; i++) {
|
||||||
Set<List<Token>> tokenListSet1;
|
Set<List<Token>> tokenListSet1;
|
||||||
Set<List<Token>> tokenListSet2;
|
Set<List<Token>> tokenListSet2;
|
||||||
|
|
|
@ -10,8 +10,6 @@ package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.google.errorprone.annotations.MustBeClosed;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author overflow - Initial contribution and API
|
* @author overflow - Initial contribution and API
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue