mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
refactoring, better exception handling, changes to error detection
exception messages now contain the the rule that caused the problem
This commit is contained in:
parent
5aba8ab724
commit
a6993a01f7
14 changed files with 384 additions and 133 deletions
|
@ -17,8 +17,8 @@ import org.eclipse.xtext.resource.XtextResource;
|
|||
import org.eclipse.xtext.testing.GlobalRegistries;
|
||||
import org.eclipse.xtext.tests.AbstractXtextTests;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.HoistingProcessor;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.TokenAnalysisAbortedException;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.guards.HoistingGuard;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.pathAnalysis.TokenAnalysisAbortedException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -79,7 +79,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertTrue(guard.isTrivial());
|
||||
assertFalse(guard.hasTerminal());
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertFalse(guard.hasTerminal());
|
||||
assertEquals("(p0)", guard.render());
|
||||
|
@ -112,7 +112,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(p0)", guard.render());
|
||||
|
@ -129,7 +129,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertTrue(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertTrue(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(p0)", guard.render());
|
||||
|
@ -180,7 +180,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((p0) && (p1))", guard.render());
|
||||
|
@ -198,7 +198,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(p0)", guard.render());
|
||||
|
@ -216,7 +216,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertTrue(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(p0)", guard.render());
|
||||
|
@ -249,7 +249,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("s", 1) + " || (p1)) && (" + getSyntaxForKeywordToken("a", 1) + " || (p0)))", guard.render());
|
||||
|
@ -266,7 +266,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("s", 1) + " || (p1)) && (" + getSyntaxForKeywordToken("a", 1) + " || (p0)))", guard.render());
|
||||
|
@ -284,7 +284,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
//assertEquals("((" + getSyntaxForKeywordToken("s", 1) + " || (p2)) && ((" + getSyntaxForKeywordToken("a", 1) + " && " + getSyntaxForKeywordToken("b", 1) + ") || ((" + getSyntaxForKeywordToken("a", 1)+ " || (p0)) && (" + getSyntaxForKeywordToken("b", 1) + " || (p1)))))", guard.render());
|
||||
|
@ -303,7 +303,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertFalse(guard.hasTerminal());
|
||||
assertEquals("((p0) || (p1))", guard.render());
|
||||
|
@ -321,7 +321,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("a", 1) + " || (p0)) && (" + getSyntaxForKeywordToken("b", 1) + " || (p1)))", guard.render());
|
||||
|
@ -341,7 +341,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(((" + getSyntaxForKeywordToken("a", 1) + " && " + getSyntaxForKeywordToken("b", 1) + ") || (p0)) && ((" + getSyntaxForKeywordToken("c", 1) + " && " + getSyntaxForKeywordToken("d", 1) + ") || (p1)))", guard.render());
|
||||
|
@ -360,7 +360,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("a", 2) + " || (p0)) && (" + getSyntaxForKeywordToken("b", 2) + " || (p1)))", guard.render());
|
||||
|
@ -380,7 +380,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("j", 10) + " || ((p0) || (p1))) && (" + getSyntaxForKeywordToken("k", 10) + " || (p2)))", guard.render());
|
||||
|
@ -398,7 +398,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertTrue(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
}
|
||||
|
@ -415,7 +415,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("(" + getSyntaxForKeywordToken("a", 1) + " || (p0))", guard.render());
|
||||
|
@ -438,7 +438,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((" + getSyntaxForKeywordToken("b", 2) + " || ((p0) && (p2))) && (" + getSyntaxForKeywordToken("c", 2) + " || ((p0) && (p3))) && (" + getSyntaxForKeywordToken("d", 3) + " || (p1)))", guard.render());
|
||||
|
@ -461,7 +461,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
|
||||
|
@ -483,7 +483,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
|
||||
|
@ -502,7 +502,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
}
|
||||
|
||||
@Test(expected = TokenAnalysisAbortedException.class)
|
||||
|
@ -517,7 +517,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
}
|
||||
|
||||
@Test(expected = TokenAnalysisAbortedException.class)
|
||||
|
@ -533,7 +533,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
}
|
||||
|
||||
// symbolic analysis not yet implemented
|
||||
|
@ -550,7 +550,7 @@ public class HoistingProcessorTest extends AbstractXtextTests {
|
|||
Grammar grammar = ((Grammar) resource.getContents().get(0));
|
||||
AbstractRule rule = getRule(grammar, "S");
|
||||
|
||||
HoistingGuard guard = hoistingProcessor.findGuardForElement(rule.getAlternatives());
|
||||
HoistingGuard guard = hoistingProcessor.findHoistingGuard(rule.getAlternatives());
|
||||
assertFalse(guard.isTrivial());
|
||||
assertTrue(guard.hasTerminal());
|
||||
assertEquals("((p0) || (p1))", guard.render());
|
||||
|
|
|
@ -37,7 +37,6 @@ import static extension org.eclipse.xtext.xtext.generator.parser.antlr.AntlrGram
|
|||
import static extension org.eclipse.xtext.xtext.generator.parser.antlr.TerminalRuleToLexerBody.*
|
||||
import org.eclipse.xtext.xtext.generator.util.SyntheticTerminalDetector
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.HoistingProcessor
|
||||
import java.lang.reflect.Parameter
|
||||
import org.eclipse.xtext.AbstractSemanticPredicate
|
||||
import org.eclipse.xtext.JavaAction
|
||||
import org.eclipse.xtext.GatedSemanticPredicate
|
||||
|
@ -337,7 +336,7 @@ abstract class AbstractAntlrGrammarGenerator {
|
|||
protected dispatch def String dataTypeEbnf2(AbstractElement it, boolean supportActions) '''ERROR «eClass.name» not matched'''
|
||||
|
||||
protected dispatch def String dataTypeEbnf2(Alternatives it, boolean supportActions) '''
|
||||
«FOR e:elements SEPARATOR '\n |'»«e.findGuardForElement.renderPredicate»«e.dataTypeEbnf(supportActions)»«ENDFOR»
|
||||
«FOR e:elements SEPARATOR '\n |'»«e.findHoistingGuard.renderPredicate»«e.dataTypeEbnf(supportActions)»«ENDFOR»
|
||||
'''
|
||||
|
||||
protected dispatch def String dataTypeEbnf2(Group it, boolean supportActions) '''
|
||||
|
@ -359,7 +358,7 @@ abstract class AbstractAntlrGrammarGenerator {
|
|||
protected dispatch def String ebnf2(AbstractElement it, AntlrOptions options, boolean supportActions) '''ERROR «eClass.name» not matched'''
|
||||
|
||||
protected dispatch def String ebnf2(Alternatives it, AntlrOptions options, boolean supportActions) '''
|
||||
«FOR element:elements SEPARATOR '\n |'»«element.findGuardForElement.renderPredicate»«element.ebnf(options, supportActions)»«ENDFOR»
|
||||
«FOR element:elements SEPARATOR '\n |'»«element.findHoistingGuard.renderPredicate»«element.ebnf(options, supportActions)»«ENDFOR»
|
||||
'''
|
||||
|
||||
protected dispatch def String ebnf2(Group it, AntlrOptions options, boolean supportActions) '''
|
||||
|
|
|
@ -161,7 +161,7 @@ class AntlrContentAssistGrammarGenerator extends AbstractAntlrGrammarWithActions
|
|||
int stackSize = keepStackSize();
|
||||
}
|
||||
:
|
||||
«FOR element : elements SEPARATOR '\n|'»«element.findGuardForElement.renderPredicate»«element.ebnf(options, false)»«ENDFOR»
|
||||
«FOR element : elements SEPARATOR '\n|'»«element.findHoistingGuard.renderPredicate»«element.ebnf(options, false)»«ENDFOR»
|
||||
;
|
||||
finally {
|
||||
restoreStackSize(stackSize);
|
||||
|
|
|
@ -24,6 +24,7 @@ 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.Group;
|
||||
import org.eclipse.xtext.JavaAction;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
|
@ -32,6 +33,9 @@ import org.eclipse.xtext.XtextFactory;
|
|||
import org.eclipse.xtext.util.Tuples;
|
||||
import static org.eclipse.xtext.GrammarUtil.*;
|
||||
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions.OptionalCardinalityWithoutContextException;
|
||||
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.guards.AlternativeTokenSequenceGuard;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.guards.AlternativesGuard;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.guards.GroupGuard;
|
||||
|
@ -64,12 +68,12 @@ public class HoistingProcessor {
|
|||
}
|
||||
|
||||
// TODO: handling for TokenAnalysisAbortedException
|
||||
private HoistingGuard findGuardForAlternatives(Alternatives alternatives) {
|
||||
private HoistingGuard findGuardForAlternatives(Alternatives alternatives, AbstractRule currentRule) {
|
||||
log.info("find guard for alternative");
|
||||
|
||||
List<AbstractElement> paths = alternatives.getElements();
|
||||
List<MergedPathGuard> guards = paths.stream()
|
||||
.map(this::findGuardForElement)
|
||||
.map(p -> findGuardForElement(p, currentRule))
|
||||
.map(MergedPathGuard::new)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -84,20 +88,24 @@ public class HoistingProcessor {
|
|||
return HoistingGuard.unguarded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log.info("path identity check");
|
||||
int size = paths.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
if (analysis.arePathsIdentical(paths.get(i), paths.get(j))) {
|
||||
guards.get(i).add(guards.get(j));
|
||||
|
||||
paths.remove(j);
|
||||
guards.remove(j);
|
||||
j--;
|
||||
size--;
|
||||
try {
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
if (analysis.arePathsIdentical(paths.get(i), paths.get(j))) {
|
||||
guards.get(i).add(guards.get(j));
|
||||
|
||||
paths.remove(j);
|
||||
guards.remove(j);
|
||||
j--;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TokenAnalysisAbortedException e) {
|
||||
throw new TokenAnalysisAbortedException(e.getMessage(), e, currentRule);
|
||||
}
|
||||
|
||||
log.info("paths:" + paths);
|
||||
|
@ -107,21 +115,25 @@ public class HoistingProcessor {
|
|||
// if all paths are empty the above step will eliminate all paths
|
||||
// -> size = 1
|
||||
if (size > 1) {
|
||||
return StreamUtils.zip(
|
||||
analysis.findMinimalPathDifference(paths).stream()
|
||||
.map(a -> a.stream()
|
||||
.map(s -> s.stream()
|
||||
.map(SingleTokenGuard::new)
|
||||
.collect(Collectors.toList())
|
||||
try {
|
||||
return StreamUtils.zip(
|
||||
analysis.findMinimalPathDifference(paths).stream()
|
||||
.map(a -> a.stream()
|
||||
.map(s -> s.stream()
|
||||
.map(SingleTokenGuard::new)
|
||||
.collect(Collectors.toList())
|
||||
)
|
||||
.map(TokenSequenceGuard::new)
|
||||
.collect(Collectors.toList())
|
||||
)
|
||||
.map(TokenSequenceGuard::new)
|
||||
.collect(Collectors.toList())
|
||||
)
|
||||
.map(AlternativeTokenSequenceGuard::new),
|
||||
guards.stream(),
|
||||
(TokenGuard tokenGuard, MergedPathGuard pathGuard) -> Tuples.pair(tokenGuard, pathGuard)
|
||||
).map(p -> new PathGuard(p.getFirst(), p.getSecond()))
|
||||
.collect(AlternativesGuard.collector());
|
||||
.map(AlternativeTokenSequenceGuard::new),
|
||||
guards.stream(),
|
||||
(TokenGuard tokenGuard, MergedPathGuard pathGuard) -> Tuples.pair(tokenGuard, pathGuard)
|
||||
).map(p -> new PathGuard(p.getFirst(), p.getSecond()))
|
||||
.collect(AlternativesGuard.collector());
|
||||
} catch(TokenAnalysisAbortedException e) {
|
||||
throw new TokenAnalysisAbortedException(e.getMessage(), e, currentRule);
|
||||
}
|
||||
} else {
|
||||
return guards.get(0);
|
||||
}
|
||||
|
@ -148,7 +160,7 @@ public class HoistingProcessor {
|
|||
return elements;
|
||||
}
|
||||
|
||||
private HoistingGuard findGuardForGroup(Group group) {
|
||||
private HoistingGuard findGuardForGroup(Group group, AbstractRule currentRule) {
|
||||
log.info("find guard for group");
|
||||
|
||||
GroupGuard groupGuard = new GroupGuard();
|
||||
|
@ -162,7 +174,7 @@ public class HoistingProcessor {
|
|||
cardinality.equals("") ||
|
||||
cardinality.equals("+")) {
|
||||
|
||||
HoistingGuard guard = findGuardForElementWithTrivialCardinality(element);
|
||||
HoistingGuard guard = findGuardForElementWithTrivialCardinality(element, currentRule);
|
||||
groupGuard.add(guard);
|
||||
|
||||
// if cardinality is + and there is a terminal we don't need to consider
|
||||
|
@ -178,7 +190,6 @@ public class HoistingProcessor {
|
|||
// rewrite cardinality to alternatives
|
||||
// A? B -> A B | B
|
||||
// A* B -> A+ B | B -> A B (see above)
|
||||
// TODO: what if B is empty?
|
||||
|
||||
// we need a clone of the element because we need to set the cardinality without changing the
|
||||
// original syntax tree
|
||||
|
@ -189,6 +200,12 @@ public class HoistingProcessor {
|
|||
List<AbstractElement> remainingElementsInGroup = StreamUtils.fromIterator(iterator)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (remainingElementsInGroup.isEmpty()) {
|
||||
// B is empty
|
||||
// context is needed to generate virtual alternatives
|
||||
throw new OptionalCardinalityWithoutContextException("no context in group", currentRule);
|
||||
}
|
||||
|
||||
// make copy of first branch and add the cloned element
|
||||
List<AbstractElement> remainingElementsInGroupIncludingCurrent = new LinkedList<>(remainingElementsInGroup);
|
||||
remainingElementsInGroupIncludingCurrent.add(0, clonedElement);
|
||||
|
@ -203,7 +220,7 @@ public class HoistingProcessor {
|
|||
addElementsToCompoundElement(virtualAlternatives, Arrays.asList(virtualPathRemaining, virtualPathRemainingPlusCurrent));
|
||||
|
||||
// get Guard for virtual alternatives
|
||||
HoistingGuard guard = findGuardForElementWithTrivialCardinality(virtualAlternatives);
|
||||
HoistingGuard guard = findGuardForElementWithTrivialCardinality(virtualAlternatives, currentRule);
|
||||
groupGuard.add(guard);
|
||||
|
||||
if (guard.hasTerminal()) {
|
||||
|
@ -220,81 +237,112 @@ public class HoistingProcessor {
|
|||
return groupGuard;
|
||||
}
|
||||
|
||||
// issue: groupCache can't be Concurrent because of possible recursive calls to computeIfAbent
|
||||
// solution: atomic section
|
||||
public synchronized HoistingGuard findGuardForRule(AbstractRule rule) {
|
||||
// TODO: make private
|
||||
public HoistingGuard findGuardForRule(AbstractRule rule) {
|
||||
HoistingGuard guard = ruleCache.get(rule.getName());
|
||||
if (guard == null) {
|
||||
guard = findGuardForElement(rule.getAlternatives());
|
||||
guard = findGuardForElement(rule.getAlternatives(), rule);
|
||||
ruleCache.put(rule.getName(), guard);
|
||||
}
|
||||
return guard;
|
||||
}
|
||||
|
||||
private boolean pathHasToken(AbstractElement path) {
|
||||
private boolean pathHasTokenOrAction(AbstractElement path) {
|
||||
// we are only interested in whether or not there could be any tokens on this path
|
||||
// -> ignore cardinality
|
||||
|
||||
if (Token.isToken(path)) {
|
||||
return true;
|
||||
} else if (isEnumRuleCall(path)) {
|
||||
return true;
|
||||
} else if (path instanceof JavaAction) {
|
||||
return true;
|
||||
} else if (isParserRuleCall(path)) {
|
||||
// can not be self recursive since ANTLR uses LL(*) and therefore does not support left recursion
|
||||
return pathHasToken(((RuleCall) path).getRule().getAlternatives());
|
||||
return pathHasTokenOrAction(((RuleCall) path).getRule().getAlternatives());
|
||||
} else if (path instanceof Assignment) {
|
||||
return pathHasToken(((Assignment) path).getTerminal());
|
||||
} else if (path instanceof Group) {
|
||||
return ((Group) path).getElements().stream()
|
||||
.anyMatch(this::pathHasToken);
|
||||
} else if (path instanceof Alternatives) {
|
||||
return ((Alternatives) path).getElements().stream()
|
||||
.anyMatch(this::pathHasToken);
|
||||
return pathHasTokenOrAction(((Assignment) path).getTerminal());
|
||||
} else if (path instanceof CompoundElement) {
|
||||
return ((CompoundElement) path).getElements().stream()
|
||||
.anyMatch(this::pathHasTokenOrAction);
|
||||
} else {
|
||||
// Actions, JavaActions, Predicates, ...
|
||||
// Actions, Predicates, ...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public HoistingGuard findGuardForElement(AbstractElement element) {
|
||||
String cardinality = element.getCardinality();
|
||||
if (cardinality == null || cardinality.equals("")) {
|
||||
return findGuardForElementWithTrivialCardinality(element);
|
||||
} else if (cardinality.equals("+")) {
|
||||
return findGuardForElementWithTrivialCardinality(element);
|
||||
} else if (cardinality.equals("?") ||
|
||||
cardinality.equals("*")) {
|
||||
if (pathHasToken(element)) {
|
||||
@SuppressWarnings("unused")
|
||||
private boolean pathHasHoistablePredicate(AbstractElement path) {
|
||||
// we are only interested in whether or not there could be any hoistable predicate on this path
|
||||
// -> ignore cardinality
|
||||
|
||||
if (path instanceof AbstractSemanticPredicate) {
|
||||
return true;
|
||||
} else if (isParserRuleCall(path)) {
|
||||
// can not be self recursive since ANTLR uses LL(*) and therefore does not support left recursion
|
||||
return pathHasHoistablePredicate(((RuleCall) path).getRule().getAlternatives());
|
||||
} else if (path instanceof Assignment) {
|
||||
return pathHasHoistablePredicate(((Assignment) path).getTerminal());
|
||||
} else if (path instanceof Alternatives ||
|
||||
path instanceof UnorderedGroup) {
|
||||
return ((CompoundElement) path).getElements().stream()
|
||||
.anyMatch(this::pathHasHoistablePredicate);
|
||||
} else if (path instanceof Group) {
|
||||
for (AbstractElement element : ((CompoundElement) path).getElements()) {
|
||||
if (pathHasHoistablePredicate(element)) {
|
||||
return true;
|
||||
}
|
||||
if (pathHasTokenOrAction(element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// Tokens, EnumRule, Actions, JavaActions, ...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public HoistingGuard findHoistingGuard(AbstractElement element) {
|
||||
return findGuardForElement(element, containingParserRule(element));
|
||||
}
|
||||
|
||||
private HoistingGuard findGuardForElement(AbstractElement element, AbstractRule currentRule) {
|
||||
if (isTrivialCardinality(element)) {
|
||||
return findGuardForElementWithTrivialCardinality(element, currentRule);
|
||||
} else if (isOneOrMoreCardinality(element)) {
|
||||
return findGuardForElementWithTrivialCardinality(element, currentRule);
|
||||
} else if (isOptionalCardinality(element)) {
|
||||
if (pathHasTokenOrAction(element)) {
|
||||
// there might be a token in this element
|
||||
// no context accessible to construct guard
|
||||
// this does only work when analyzing group
|
||||
// TODO: generate warning
|
||||
// this is not a terminal, but there is no point constructing guards past this point
|
||||
return HoistingGuard.terminal();
|
||||
|
||||
// TODO: maybe generate warning and return terminal()
|
||||
throw new OptionalCardinalityWithoutContextException("optional cardinality is only supported in groups", currentRule);
|
||||
} else {
|
||||
// element with cardinality ? or * has no token
|
||||
// element with cardinality ? or * has no token or action
|
||||
// -> the path is accessible whether or not this element is guarded
|
||||
// -> we can assume it is unguarded
|
||||
return HoistingGuard.unguarded();
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("unknown cardinality: " + cardinality);
|
||||
throw new IllegalArgumentException("unknown cardinality: " + element.getCardinality());
|
||||
}
|
||||
}
|
||||
|
||||
private HoistingGuard findGuardForElementWithTrivialCardinality(AbstractElement element) {
|
||||
private HoistingGuard findGuardForElementWithTrivialCardinality(AbstractElement element, AbstractRule currentRule) {
|
||||
log.info("finding guard for element: " + element.toString());
|
||||
|
||||
if (element instanceof Alternatives) {
|
||||
return findGuardForAlternatives((Alternatives) element);
|
||||
return findGuardForAlternatives((Alternatives) element, currentRule);
|
||||
} else if (element instanceof Group) {
|
||||
// issue: groupCache can't be Concurrent because of possible recursive calls to computeIfAbent
|
||||
// solution: atomic section
|
||||
synchronized (groupCache) {
|
||||
HoistingGuard guard = groupCache.get(element);
|
||||
if (guard == null) {
|
||||
guard = findGuardForGroup((Group) element);
|
||||
groupCache.put((Group) element, guard);
|
||||
}
|
||||
return guard;
|
||||
HoistingGuard guard = groupCache.get(element);
|
||||
if (guard == null) {
|
||||
guard = findGuardForGroup((Group) element, currentRule);
|
||||
groupCache.put((Group) element, guard);
|
||||
}
|
||||
return guard;
|
||||
} else if (element instanceof AbstractSemanticPredicate) {
|
||||
return new PredicateGuard((AbstractSemanticPredicate) element);
|
||||
} else if (Token.isToken(element)) {
|
||||
|
@ -308,12 +356,21 @@ public class HoistingProcessor {
|
|||
} else if (element instanceof JavaAction) {
|
||||
return HoistingGuard.action();
|
||||
} else if (element instanceof UnorderedGroup) {
|
||||
// TODO: maybe add warning and return unguarded
|
||||
throw new UnsupportedOperationException("unordered groups are only supported in groups");
|
||||
if (pathHasTokenOrAction(element)) {
|
||||
// if unordered group has tokens or actions we need the context which is not available here
|
||||
// only works when analyzing groups
|
||||
|
||||
// TODO: maybe add warning and return unguarded
|
||||
throw new UnsupportedConstructException("unordered groups are only supported in groups", currentRule);
|
||||
} else {
|
||||
// the path is accessible whether or not any guard is satisfied
|
||||
// -> assume it's unguarded
|
||||
return HoistingGuard.unguarded();
|
||||
}
|
||||
} else if (element instanceof Assignment) {
|
||||
return findGuardForElement(((Assignment) element).getTerminal());
|
||||
return findGuardForElement(((Assignment) element).getTerminal(), currentRule);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("element not supported: " + element.toString());
|
||||
throw new UnsupportedConstructException("element not supported: " + element.toString(), currentRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2021 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions;
|
||||
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
||||
*/
|
||||
public class HoistingException extends RuntimeException {
|
||||
private static final long serialVersionUID = 6074715133295241743L;
|
||||
|
||||
private AbstractRule rule;
|
||||
|
||||
public HoistingException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public HoistingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public HoistingException(String message, Throwable cause, AbstractRule rule) {
|
||||
super(message, cause);
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
public HoistingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public HoistingException(String message, AbstractRule rule) {
|
||||
super(message);
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
public HoistingException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public HoistingException(Throwable cause, AbstractRule rule) {
|
||||
super(cause);
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
if (rule == null) {
|
||||
return super.getMessage();
|
||||
} else {
|
||||
return rule.getName() + ": " + super.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2021 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions;
|
||||
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
||||
*/
|
||||
public class OptionalCardinalityWithoutContextException extends UnsupportedConstructException {
|
||||
private static final long serialVersionUID = -3958747238452206971L;
|
||||
|
||||
public OptionalCardinalityWithoutContextException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(String message, AbstractRule rule) {
|
||||
super(message, rule);
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(String message, Throwable cause, AbstractRule rule) {
|
||||
super(message, cause, rule);
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(Throwable cause, AbstractRule rule) {
|
||||
super(cause, rule);
|
||||
}
|
||||
|
||||
public OptionalCardinalityWithoutContextException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.pathAnalysis;
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2021 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions;
|
||||
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
||||
*/
|
||||
public class TokenAnalysisAbortedException extends HoistingException {
|
||||
private static final long serialVersionUID = 4303267001950479292L;
|
||||
|
||||
public TokenAnalysisAbortedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(String message, AbstractRule rule) {
|
||||
super(message, rule);
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(String message, Throwable cause, AbstractRule rule) {
|
||||
super(message, cause, rule);
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(Throwable cause, AbstractRule rule) {
|
||||
super(cause, rule);
|
||||
}
|
||||
|
||||
public TokenAnalysisAbortedException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2021 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.exceptions;
|
||||
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
||||
*/
|
||||
public class UnsupportedConstructException extends HoistingException {
|
||||
private static final long serialVersionUID = 637006930813191613L;
|
||||
|
||||
public UnsupportedConstructException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(String message, AbstractRule rule) {
|
||||
super(message, rule);
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(String message, Throwable cause, AbstractRule rule) {
|
||||
super(message, cause, rule);
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(Throwable cause, AbstractRule rule) {
|
||||
super(cause, rule);
|
||||
}
|
||||
|
||||
public UnsupportedConstructException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -29,6 +29,8 @@ import org.eclipse.xtext.Group;
|
|||
import org.eclipse.xtext.JavaAction;
|
||||
import org.eclipse.xtext.RuleCall;
|
||||
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.token.Token;
|
||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.MutablePrimitiveWrapper;
|
||||
|
||||
|
@ -56,7 +58,7 @@ public class TokenAnalysis {
|
|||
result = prefix;
|
||||
if (needsLength) {
|
||||
// analysis is not done but there are no more mandatory tokens
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("needed path length not satisfied due to optional cardinality");
|
||||
}
|
||||
} else {
|
||||
result = TokenAnalysisPaths.empty(prefix);
|
||||
|
@ -102,7 +104,7 @@ public class TokenAnalysis {
|
|||
result = prefix;
|
||||
if (needsLength) {
|
||||
// analysis is not done but there are no more mandatory tokens
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("needed path length not satisfied due to optional cardinality");
|
||||
}
|
||||
} else {
|
||||
result = TokenAnalysisPaths.empty(prefix);
|
||||
|
@ -123,7 +125,7 @@ public class TokenAnalysis {
|
|||
|
||||
if (needsLength && !current.isDone()) {
|
||||
// analysis is not done but there are no more mandatory tokens
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("needed path length not satisfied");
|
||||
}
|
||||
|
||||
result = result.merge(current);
|
||||
|
@ -144,7 +146,7 @@ public class TokenAnalysis {
|
|||
if (isOptionalCardinality(path)) {
|
||||
result = prefix;
|
||||
if (needsLength) {
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("needed path length not satisfied due to optional cardinality");
|
||||
}
|
||||
} else {
|
||||
result = TokenAnalysisPaths.empty(prefix);
|
||||
|
@ -178,7 +180,7 @@ public class TokenAnalysis {
|
|||
}
|
||||
|
||||
if (needsLength) {
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("needed path length not satisfied");
|
||||
}
|
||||
} while(loop);
|
||||
|
||||
|
@ -248,7 +250,7 @@ public class TokenAnalysis {
|
|||
|
||||
// we can't analyze the paths any further
|
||||
// TODO maybe assume paths are equal and show warning instead of exception
|
||||
throw new TokenAnalysisAbortedException();
|
||||
throw new TokenAnalysisAbortedException("token limit exhausted while looking for identical paths");
|
||||
}
|
||||
|
||||
public boolean arePathsIdentical(AbstractElement path1, AbstractElement path2) {
|
||||
|
@ -269,8 +271,13 @@ public class TokenAnalysis {
|
|||
}
|
||||
}
|
||||
// we tried all possible combinations
|
||||
// TODO: can only happen if no symbolic analysis is implemented
|
||||
// -> abort
|
||||
throw new TokenAnalysisAbortedException();
|
||||
if (limit.get().equals(config.getTokenLimit())) {
|
||||
throw new TokenAnalysisAbortedException("token limit exhausted while searching for minimal differences");
|
||||
} else {
|
||||
throw new TokenAnalysisAbortedException("path length exhausted while searching for minimal differences");
|
||||
}
|
||||
}
|
||||
private boolean tokenCombinations(long prefix, int prefixLength, int ones, Function<List<Integer>, Boolean> callback, MutablePrimitiveWrapper<Integer> limit) {
|
||||
if (ones == 0) {
|
||||
|
@ -295,7 +302,6 @@ public class TokenAnalysis {
|
|||
// tokens exhausted; abort current prefix
|
||||
// set limit for calling functions so this index is not checked again
|
||||
limit.set(i);
|
||||
log.info("tokens exhausted");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2021 itemis AG (http://www.itemis.eu) and others.
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.pathAnalysis;
|
||||
|
||||
/**
|
||||
* @author overflow - Initial contribution and API
|
||||
*/
|
||||
public class TokenAnalysisAbortedException extends RuntimeException {
|
||||
private static final long serialVersionUID = 4303267001950479292L;
|
||||
}
|
|
@ -818,7 +818,7 @@ public abstract class AbstractAntlrGrammarGenerator {
|
|||
} else {
|
||||
_builder.appendImmediate("\n |", "");
|
||||
}
|
||||
String _renderPredicate = this._hoistingProcessor.findGuardForElement(e).renderPredicate();
|
||||
String _renderPredicate = this._hoistingProcessor.findHoistingGuard(e).renderPredicate();
|
||||
_builder.append(_renderPredicate);
|
||||
String _dataTypeEbnf = this.dataTypeEbnf(e, supportActions);
|
||||
_builder.append(_dataTypeEbnf);
|
||||
|
@ -890,7 +890,7 @@ public abstract class AbstractAntlrGrammarGenerator {
|
|||
} else {
|
||||
_builder.appendImmediate("\n |", "");
|
||||
}
|
||||
String _renderPredicate = this._hoistingProcessor.findGuardForElement(element).renderPredicate();
|
||||
String _renderPredicate = this._hoistingProcessor.findHoistingGuard(element).renderPredicate();
|
||||
_builder.append(_renderPredicate);
|
||||
String _ebnf = this.ebnf(element, options, supportActions);
|
||||
_builder.append(_ebnf);
|
||||
|
|
|
@ -432,7 +432,7 @@ public class AntlrContentAssistGrammarGenerator extends AbstractAntlrGrammarWith
|
|||
} else {
|
||||
_builder.appendImmediate("\n|", "\t");
|
||||
}
|
||||
String _renderPredicate = this._hoistingProcessor.findGuardForElement(element).renderPredicate();
|
||||
String _renderPredicate = this._hoistingProcessor.findHoistingGuard(element).renderPredicate();
|
||||
_builder.append(_renderPredicate, "\t");
|
||||
String _ebnf = this.ebnf(element, options, false);
|
||||
_builder.append(_ebnf, "\t");
|
||||
|
|
|
@ -586,6 +586,10 @@ public class GrammarUtil {
|
|||
public static boolean isMultipleAssignment(Action a) {
|
||||
return "+=".equals(a.getOperator());
|
||||
}
|
||||
|
||||
public static boolean isTrivialCardinality(AbstractElement e) {
|
||||
return e.getCardinality() == null || e.getCardinality().equals("");
|
||||
}
|
||||
|
||||
public static boolean isOptionalCardinality(AbstractElement e) {
|
||||
return e.getCardinality() != null && (e.getCardinality().equals("?") || e.getCardinality().equals("*"));
|
||||
|
|
Loading…
Reference in a new issue