fixed problem with repeated empty paths in context

no-progress-in-loop-error is interpreted as nested identity paths - this
is wrong

fix: enable endless loop shortcut in context analysis
This commit is contained in:
overflowerror 2022-01-20 14:00:32 +01:00
parent 9dfc0b4bfc
commit aad95fa670
2 changed files with 24 additions and 5 deletions

View file

@ -1087,8 +1087,6 @@ public class HoistingProcessorTest extends AbstractXtextTests {
// @formatter:off // @formatter:off
String model = String model =
MODEL_PREAMBLE + MODEL_PREAMBLE +
"tokenLimit 4\n" +
"hoistingDebug\n" +
"S: a=A ;\n" + "S: a=A ;\n" +
"A: $$ p0 $$?=> 'a' \n" + "A: $$ p0 $$?=> 'a' \n" +
" | $$ p1 $$?=> 'a' s=S ;\n"; " | $$ p1 $$?=> 'a' s=S ;\n";
@ -1109,8 +1107,6 @@ public class HoistingProcessorTest extends AbstractXtextTests {
// @formatter:off // @formatter:off
String model = String model =
MODEL_PREAMBLE + MODEL_PREAMBLE +
"tokenLimit 4\n" +
"hoistingDebug\n" +
"S: $$ p0 $$?=> 'a' \n" + "S: $$ p0 $$?=> 'a' \n" +
" | $$ p1 $$?=> 'a' s=S ;\n"; " | $$ p1 $$?=> 'a' s=S ;\n";
// @formatter:off // @formatter:off
@ -1124,4 +1120,26 @@ public class HoistingProcessorTest extends AbstractXtextTests {
assertTrue(guard.hasTerminal()); assertTrue(guard.hasTerminal());
assertEquals("((" + getSyntaxForEofToken(2) + " || (p0)) && (" + getSyntaxForKeywordToken("a", 2) + " || (p1)))", guard.render()); 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());
}
} }

View file

@ -185,7 +185,8 @@ public class TokenAnalysis {
log.info("context element: " + abstractElementToShortString(element)); log.info("context element: " + abstractElementToShortString(element));
TokenAnalysisPaths path = new TokenAnalysisPaths(prefix); TokenAnalysisPaths path = new TokenAnalysisPaths(prefix);
path.resetProgress(); 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 (!path.isDone() && element != null) {
if (callStack.contains(element) && !path.hasProgress()) { if (callStack.contains(element) && !path.hasProgress()) {
throw new EmptyRecursionPathInContextAnalysisException("no progress in recursion"); throw new EmptyRecursionPathInContextAnalysisException("no progress in recursion");