Merge pull request #1582 from sharwell/optional-analysis

Fix multiple bugs with the new optional element analysis
This commit is contained in:
Terence Parr 2017-01-06 07:04:04 -08:00 committed by GitHub
commit 33ac0c3611
2 changed files with 42 additions and 7 deletions

View File

@ -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();

View File

@ -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;