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 b544165c1..44f2d68c4 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 @@ -1087,8 +1087,6 @@ public class HoistingProcessorTest extends AbstractXtextTests { // @formatter:off String model = MODEL_PREAMBLE + - "tokenLimit 4\n" + - "hoistingDebug\n" + "S: a=A ;\n" + "A: $$ p0 $$?=> 'a' \n" + " | $$ p1 $$?=> 'a' s=S ;\n"; @@ -1109,8 +1107,6 @@ public class HoistingProcessorTest extends AbstractXtextTests { // @formatter:off String model = MODEL_PREAMBLE + - "tokenLimit 4\n" + - "hoistingDebug\n" + "S: $$ p0 $$?=> 'a' \n" + " | $$ p1 $$?=> 'a' s=S ;\n"; // @formatter:off @@ -1124,4 +1120,26 @@ public class HoistingProcessorTest extends AbstractXtextTests { assertTrue(guard.hasTerminal()); assertEquals("((" + getSyntaxForEofToken(2) + " || (p0)) && (" + getSyntaxForKeywordToken("a", 2) + " || (p1)))", guard.render()); } + + @Test + public void testRepeatableContextWithEmptyPath_bug_expectCorrectResult() throws Exception { + // @formatter:off + String model = + MODEL_PREAMBLE + + "hoistingDebug\n" + + "S: A C+ ;\n" + + "A: $$ p0 $$?=> 'a' " + + " | $$ p1 $$?=> 'a' 'b' ;\n" + + "C: 'c'? ;\n"; + // @formatter:off + XtextResource resource = getResourceFromString(model); + Grammar grammar = ((Grammar) resource.getContents().get(0)); + hoistingProcessor.init(grammar); + AbstractRule rule = getRule(grammar, "A"); + + HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives()); + assertFalse(guard.isTrivial()); + assertTrue(guard.hasTerminal()); + assertEquals("(((" + getSyntaxForEofToken(2) + " && " + getSyntaxForKeywordToken("c", 2) + ") || (p0)) && (" + getSyntaxForKeywordToken("b", 2) + " || (p1)))", guard.render()); + } } 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 0a1f44c75..b4cccbba1 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 @@ -185,7 +185,8 @@ public class TokenAnalysis { log.info("context element: " + abstractElementToShortString(element)); TokenAnalysisPaths path = new TokenAnalysisPaths(prefix); path.resetProgress(); - path = getTokenPaths(element, path, false, false, shortcutEndlessLoops); + // shortcut endless loops instead of throwing exception + path = getTokenPaths(element, path, false, false, true); if (!path.isDone() && element != null) { if (callStack.contains(element) && !path.hasProgress()) { throw new EmptyRecursionPathInContextAnalysisException("no progress in recursion");