forked from jasder/antlr
Merge pull request #1582 from sharwell/optional-analysis
Fix multiple bugs with the new optional element analysis
This commit is contained in:
commit
33ac0c3611
|
@ -96,7 +96,7 @@ public class ElementFrequenciesVisitor extends GrammarTreeVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert a != SENTINEL;
|
assert a != SENTINEL;
|
||||||
FrequencySet<String> result = combineAndClip(a, b, 1);
|
FrequencySet<String> result = combineAndClip(a, b, Integer.MAX_VALUE);
|
||||||
for (Map.Entry<String, MutableInt> entry : result.entrySet()) {
|
for (Map.Entry<String, MutableInt> entry : result.entrySet()) {
|
||||||
entry.getValue().v = Math.min(a.count(entry.getKey()), b.count(entry.getKey()));
|
entry.getValue().v = Math.min(a.count(entry.getKey()), b.count(entry.getKey()));
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,31 @@ public class ElementFrequenciesVisitor extends GrammarTreeVisitor {
|
||||||
minFrequencies.push(combineAndClip(minFrequencies.pop(), minFrequencies.pop(), 2));
|
minFrequencies.push(combineAndClip(minFrequencies.pop(), minFrequencies.pop(), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enterBlockSet(GrammarAST tree) {
|
||||||
|
frequencies.push(new FrequencySet<String>());
|
||||||
|
minFrequencies.push(new FrequencySet<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void exitBlockSet(GrammarAST tree) {
|
||||||
|
for (Map.Entry<String, MutableInt> entry : frequencies.peek().entrySet()) {
|
||||||
|
// This visitor counts a block set as a sequence of elements, not a
|
||||||
|
// sequence of alternatives of elements. Reset the count back to 1
|
||||||
|
// for all items when leaving the set to ensure duplicate entries in
|
||||||
|
// the set are treated as a maximum of one item.
|
||||||
|
entry.getValue().v = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minFrequencies.peek().size() > 1) {
|
||||||
|
// Everything is optional
|
||||||
|
minFrequencies.peek().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
frequencies.push(combineAndClip(frequencies.pop(), frequencies.pop(), 2));
|
||||||
|
minFrequencies.push(combineAndClip(minFrequencies.pop(), minFrequencies.pop(), 2));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void exitSubrule(GrammarAST tree) {
|
protected void exitSubrule(GrammarAST tree) {
|
||||||
if (tree.getType() == CLOSURE || tree.getType() == POSITIVE_CLOSURE) {
|
if (tree.getType() == CLOSURE || tree.getType() == POSITIVE_CLOSURE) {
|
||||||
|
@ -185,7 +210,7 @@ public class ElementFrequenciesVisitor extends GrammarTreeVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tree.getType() == CLOSURE) {
|
if (tree.getType() == CLOSURE || tree.getType() == OPTIONAL) {
|
||||||
// Everything inside a closure is optional, so the minimum
|
// Everything inside a closure is optional, so the minimum
|
||||||
// number of occurrences for all elements is 0.
|
// number of occurrences for all elements is 0.
|
||||||
minFrequencies.peek().clear();
|
minFrequencies.peek().clear();
|
||||||
|
|
|
@ -171,8 +171,9 @@ public class RuleFunction extends OutputModelObject {
|
||||||
*/
|
*/
|
||||||
public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
|
public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
|
||||||
Set<String> needsList = new HashSet<String>();
|
Set<String> needsList = new HashSet<String>();
|
||||||
Set<String> optional = new HashSet<String>();
|
Set<String> nonOptional = new HashSet<String>();
|
||||||
List<GrammarAST> allRefs = new ArrayList<GrammarAST>();
|
List<GrammarAST> allRefs = new ArrayList<GrammarAST>();
|
||||||
|
boolean firstAlt = true;
|
||||||
for (AltAST ast : altASTs) {
|
for (AltAST ast : altASTs) {
|
||||||
IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF);
|
IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF);
|
||||||
List<GrammarAST> refs = ast.getNodesWithType(reftypes);
|
List<GrammarAST> refs = ast.getNodesWithType(reftypes);
|
||||||
|
@ -182,13 +183,22 @@ public class RuleFunction extends OutputModelObject {
|
||||||
FrequencySet<String> altFreq = minAndAltFreq.b;
|
FrequencySet<String> altFreq = minAndAltFreq.b;
|
||||||
for (GrammarAST t : refs) {
|
for (GrammarAST t : refs) {
|
||||||
String refLabelName = t.getText();
|
String refLabelName = t.getText();
|
||||||
if (minFreq.count(refLabelName) == 0) {
|
|
||||||
optional.add(refLabelName);
|
|
||||||
}
|
|
||||||
if ( altFreq.count(refLabelName)>1 ) {
|
if ( altFreq.count(refLabelName)>1 ) {
|
||||||
needsList.add(refLabelName);
|
needsList.add(refLabelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (firstAlt && minFreq.count(refLabelName) != 0) {
|
||||||
|
nonOptional.add(refLabelName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String ref : nonOptional.toArray(new String[nonOptional.size()])) {
|
||||||
|
if (minFreq.count(ref) == 0) {
|
||||||
|
nonOptional.remove(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
firstAlt = false;
|
||||||
}
|
}
|
||||||
Set<Decl> decls = new LinkedHashSet<Decl>();
|
Set<Decl> decls = new LinkedHashSet<Decl>();
|
||||||
for (GrammarAST t : allRefs) {
|
for (GrammarAST t : allRefs) {
|
||||||
|
@ -196,7 +206,7 @@ public class RuleFunction extends OutputModelObject {
|
||||||
List<Decl> d = getDeclForAltElement(t,
|
List<Decl> d = getDeclForAltElement(t,
|
||||||
refLabelName,
|
refLabelName,
|
||||||
needsList.contains(refLabelName),
|
needsList.contains(refLabelName),
|
||||||
optional.contains(refLabelName));
|
!nonOptional.contains(refLabelName));
|
||||||
decls.addAll(d);
|
decls.addAll(d);
|
||||||
}
|
}
|
||||||
return decls;
|
return decls;
|
||||||
|
|
Loading…
Reference in New Issue