mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 08:18:55 +00:00
fixed problem with context analysis
non-trivial quantifiers in context path are not handled correctly. change to getNextElementsInContext(): add non-trivially quantified elements in path (except first element because of potential endless recursion) to result set
This commit is contained in:
parent
e5f08c34aa
commit
a5df42591b
1 changed files with 60 additions and 69 deletions
|
@ -11,7 +11,6 @@ package org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.pathAnalysis;
|
||||||
import static org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.DebugUtils.*;
|
import static org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.DebugUtils.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -45,7 +44,6 @@ import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.DebugUtils;
|
||||||
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.MutablePrimitiveWrapper;
|
import org.eclipse.xtext.xtext.generator.parser.antlr.hoisting.utils.MutablePrimitiveWrapper;
|
||||||
|
|
||||||
import static org.eclipse.xtext.GrammarUtil.*;
|
import static org.eclipse.xtext.GrammarUtil.*;
|
||||||
import static org.eclipse.xtext.EcoreUtil2.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author overflow - Initial contribution and API
|
* @author overflow - Initial contribution and API
|
||||||
|
@ -61,65 +59,65 @@ public class TokenAnalysis {
|
||||||
this.grammar = grammar;
|
this.grammar = grammar;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AbstractElement getContainer(AbstractElement element) {
|
private List<AbstractElement> getNextElementsInContext(AbstractElement last) {
|
||||||
EObject tmp = element.eContainer();
|
List<AbstractElement> result = new ArrayList<>();
|
||||||
while (!(tmp instanceof AbstractElement)) {
|
|
||||||
if (tmp == null) {
|
AbstractElement _last = last;
|
||||||
return null;
|
AbstractElement container = last;
|
||||||
}
|
|
||||||
tmp = tmp.eContainer();
|
while(container != null && (
|
||||||
}
|
container == last ||
|
||||||
return (AbstractElement) tmp;
|
!(container instanceof CompoundElement) ||
|
||||||
}
|
container instanceof Alternatives
|
||||||
|
)
|
||||||
private CompoundElement getCompoundContainer(AbstractElement element) {
|
|
||||||
if (element instanceof CompoundElement) {
|
|
||||||
// get container of compoundElement since getContainerOfType
|
|
||||||
// would return the same element
|
|
||||||
element = getContainer(element);
|
|
||||||
if (element == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getContainerOfType(element, CompoundElement.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<AbstractElement> getNextElementsInContext(AbstractElement last) {
|
|
||||||
// TODO: deal with non-trivial cardinalities
|
|
||||||
CompoundElement container = getCompoundContainer(last);
|
|
||||||
while (container instanceof Alternatives ||
|
|
||||||
last.eContainer() instanceof Assignment
|
|
||||||
) {
|
) {
|
||||||
// skip alternatives since they have to be covered separately
|
EObject _container = _last;
|
||||||
last = getContainer(last);
|
while (_container == _last ||
|
||||||
if (last == null) {
|
!(_container instanceof AbstractElement)
|
||||||
return Arrays.asList((AbstractElement) null);
|
) {
|
||||||
|
_container = _container.eContainer();
|
||||||
|
if (_container == null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_last = container;
|
||||||
|
container = (AbstractElement) _container;
|
||||||
|
|
||||||
|
if (last != _last && isMultipleCardinality(_last)) {
|
||||||
|
// last is + or * quantified
|
||||||
|
result.add(_last);
|
||||||
}
|
}
|
||||||
container = getCompoundContainer(last);
|
|
||||||
}
|
}
|
||||||
|
last = _last;
|
||||||
|
|
||||||
log.info("getNext: " + abstractElementToShortString(last));
|
CompoundElement compoundContainer = (CompoundElement) container;
|
||||||
log.info("container: " + abstractElementToShortString(container));
|
|
||||||
|
|
||||||
if (container instanceof UnorderedGroup) {
|
if (compoundContainer == null) {
|
||||||
List<AbstractElement> result = new ArrayList<>();
|
// no container element; this is last element in a rule definition
|
||||||
result.addAll(container.getElements().stream()
|
AbstractRule rule = containingRule(last);
|
||||||
.collect(Collectors.toList())
|
List<RuleCall> calls = findAllRuleCalls(grammar, rule);
|
||||||
);
|
|
||||||
result.addAll(getNextElementsInContext(container));
|
if (calls.isEmpty()) {
|
||||||
return result;
|
// has to be start rule
|
||||||
} else if (container instanceof Group) {
|
// context is EOF
|
||||||
List<AbstractElement> elements = container.getElements();
|
result.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RuleCall call : calls) {
|
||||||
|
result.addAll(getNextElementsInContext(call));
|
||||||
|
}
|
||||||
|
} else if (compoundContainer instanceof Group) {
|
||||||
|
List<AbstractElement> elements = compoundContainer.getElements();
|
||||||
int index = elements.indexOf(last);
|
int index = elements.indexOf(last);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
log.error("context analysis: element not part of compound");
|
log.error("context analysis: element not part of compound");
|
||||||
log.info(last.eClass().getName());
|
log.info(last.eClass().getName());
|
||||||
log.info(abstractElementToString(container));
|
log.info(abstractElementToString(compoundContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = elements.size();
|
int size = elements.size();
|
||||||
AbstractElement next = null;
|
AbstractElement next = null;
|
||||||
|
|
||||||
|
// skip simple non-token-elements
|
||||||
while (index < size - 1) {
|
while (index < size - 1) {
|
||||||
next = elements.get(index + 1);
|
next = elements.get(index + 1);
|
||||||
if (!(
|
if (!(
|
||||||
|
@ -133,34 +131,27 @@ public class TokenAnalysis {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if (index < size - 1) {
|
if (index < size - 1) {
|
||||||
return Arrays.asList(next);
|
result.add(next);
|
||||||
} else {
|
} else {
|
||||||
// this is the last element
|
// this is the last element
|
||||||
return getNextElementsInContext(container);
|
if (isMultipleCardinality(compoundContainer)) {
|
||||||
|
result.add(compoundContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addAll(getNextElementsInContext(compoundContainer));
|
||||||
}
|
}
|
||||||
} else if (container == null) {
|
} else if (compoundContainer instanceof UnorderedGroup) {
|
||||||
// end of rule
|
result.addAll(compoundContainer.getElements().stream()
|
||||||
AbstractRule rule = containingRule(last);
|
.collect(Collectors.toList())
|
||||||
List<RuleCall> calls = findAllRuleCalls(grammar, rule);
|
);
|
||||||
|
result.addAll(getNextElementsInContext(compoundContainer));
|
||||||
if (calls.isEmpty()) {
|
|
||||||
// has to be start rule
|
|
||||||
// context is EOF
|
|
||||||
return Arrays.asList((AbstractElement) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AbstractElement> result = new ArrayList<>();
|
|
||||||
for (RuleCall call : calls) {
|
|
||||||
result.addAll(getNextElementsInContext(call));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("unknown compound element: " + container.eClass().getName());
|
throw new IllegalArgumentException("unknown compound element: " + container.eClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private TokenAnalysisPaths getTokenPathsContext(AbstractElement last, TokenAnalysisPaths prefix, boolean shortcutEndlessLoops) {
|
private TokenAnalysisPaths getTokenPathsContext(AbstractElement last, TokenAnalysisPaths prefix, boolean shortcutEndlessLoops) {
|
||||||
log.info("get context for: " + abstractElementToShortString(last));
|
log.info("get context for: " + abstractElementToShortString(last));
|
||||||
|
|
||||||
|
@ -180,7 +171,7 @@ 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 = getTokenPaths(element, path, false, false, shortcutEndlessLoops);
|
path = getTokenPaths(element, path, false, false, shortcutEndlessLoops);
|
||||||
if (!path.isDone() && element != null) {
|
if (!path.isDone() && element != null) {
|
||||||
path = getTokenPathsContext(element, path, shortcutEndlessLoops);
|
path = getTokenPathsContext(element, path, shortcutEndlessLoops);
|
||||||
}
|
}
|
||||||
if (path.isDone()) {
|
if (path.isDone()) {
|
||||||
|
@ -189,7 +180,7 @@ public class TokenAnalysis {
|
||||||
throw new TokenAnalysisAbortedException("context analysis failed");
|
throw new TokenAnalysisAbortedException("context analysis failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("done");
|
log.info("done");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue