From 83232e5a43d9ecd8e27bafb19eb488d2b57d712f Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sun, 5 Dec 2021 18:18:18 +0100 Subject: [PATCH] fixed bug with alternatives containing unordered groups gave exception in token analysis -> added handling for unordered groups to token analysis added test case --- .../hoisting/HoistingProcessorTest.java | 18 +++++++++++++ .../hoisting/pathAnalysis/TokenAnalysis.java | 27 ++++++++++++++++--- .../utils/MutablePrimitiveWrapper.java | 2 -- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/generator/hoisting/HoistingProcessorTest.java b/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/generator/hoisting/HoistingProcessorTest.java index 327ed557d..c2d2219f0 100644 --- a/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/generator/hoisting/HoistingProcessorTest.java +++ b/org.eclipse.xtext.tests/src/org/eclipse/xtext/xtext/generator/hoisting/HoistingProcessorTest.java @@ -579,6 +579,24 @@ public class HoistingProcessorTest extends AbstractXtextTests { 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 public void testAlternativeUnguardedPath() throws Exception { // @formatter:off diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/pathAnalysis/TokenAnalysis.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/pathAnalysis/TokenAnalysis.java index f0fe3dcb9..a4c7f8f14 100644 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/pathAnalysis/TokenAnalysis.java +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/pathAnalysis/TokenAnalysis.java @@ -25,12 +25,16 @@ import org.eclipse.xtext.AbstractSemanticPredicate; import org.eclipse.xtext.Action; import org.eclipse.xtext.Alternatives; import org.eclipse.xtext.Assignment; +import org.eclipse.xtext.CompoundElement; +import org.eclipse.xtext.GrammarUtil; import org.eclipse.xtext.Group; import org.eclipse.xtext.JavaAction; 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.exceptions.SymbolicAnalysisFailedException; 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.utils.MutablePrimitiveWrapper; @@ -48,7 +52,7 @@ public class TokenAnalysis { 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()) { return prefix; } @@ -165,7 +169,7 @@ public class TokenAnalysis { } else if (path instanceof Assignment) { current = getTokenForIndexes(((Assignment) path).getTerminal(), current, false); } else { - throw new IllegalArgumentException("unknown element: " + path.eClass().getName()); + throw new UnsupportedConstructException("unknown element: " + path.eClass().getName()); } // add path to result @@ -192,6 +196,23 @@ public class TokenAnalysis { return getTokenForIndexesAlternatives((Alternatives) path, prefix, needsLength); } else if (path instanceof Group) { 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 || path instanceof AbstractSemanticPredicate || path instanceof JavaAction @@ -217,7 +238,7 @@ public class TokenAnalysis { } 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++) { Set> tokenListSet1; Set> tokenListSet2; diff --git a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/utils/MutablePrimitiveWrapper.java b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/utils/MutablePrimitiveWrapper.java index af1538798..10731e838 100644 --- a/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/utils/MutablePrimitiveWrapper.java +++ b/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/parser/antlr/hoisting/utils/MutablePrimitiveWrapper.java @@ -10,8 +10,6 @@ package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils; import java.util.function.Function; -import com.google.errorprone.annotations.MustBeClosed; - /** * @author overflow - Initial contribution and API */