Skip to content

Commit

Permalink
Merge branch 'optional-analysis' into optimized
Browse files Browse the repository at this point in the history
  • Loading branch information
sharwell committed Jan 6, 2017
2 parents 5f376b5 + 587ea36 commit d706b5d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
30 changes: 27 additions & 3 deletions tool/src/org/antlr/v4/codegen/model/ElementFrequenciesVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.antlr.v4.misc.FrequencySet;
import org.antlr.v4.misc.MutableInt;
import org.antlr.v4.parse.GrammarTreeVisitor;
import org.antlr.v4.tool.ErrorManager;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.AltAST;
Expand Down Expand Up @@ -97,7 +96,7 @@ protected static FrequencySet<String> combineMin(FrequencySet<String> a, Frequen
}

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()) {
entry.getValue().v = Math.min(a.count(entry.getKey()), b.count(entry.getKey()));
}
Expand Down Expand Up @@ -185,6 +184,31 @@ protected void exitElement(GrammarAST tree) {
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
protected void exitSubrule(GrammarAST tree) {
if (tree.getType() == CLOSURE || tree.getType() == POSITIVE_CLOSURE) {
Expand All @@ -193,7 +217,7 @@ protected void exitSubrule(GrammarAST tree) {
}
}

if (tree.getType() == CLOSURE) {
if (tree.getType() == CLOSURE || tree.getType() == OPTIONAL) {
// Everything inside a closure is optional, so the minimum
// number of occurrences for all elements is 0.
minFrequencies.peek().clear();
Expand Down
21 changes: 16 additions & 5 deletions tool/src/org/antlr/v4/codegen/model/RuleFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,10 @@ public void fillNamedActions(OutputModelFactory factory, Rule r) {
*/
public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
Set<String> needsList = new HashSet<String>();
Set<String> optional = new HashSet<String>();
Set<String> nonOptional = new HashSet<String>();
Set<String> suppress = new HashSet<String>();
List<GrammarAST> allRefs = new ArrayList<GrammarAST>();
boolean firstAlt = true;
for (AltAST ast : altASTs) {
IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF);
List<GrammarAST> refs = ast.getNodesWithType(reftypes);
Expand All @@ -209,13 +210,23 @@ public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
if (altFreq.count(refLabelName)==0) {
suppress.add(refLabelName);
}
if (minFreq.count(refLabelName) == 0) {
optional.add(refLabelName);
}

if ( altFreq.count(refLabelName)>1 ) {
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>();
for (GrammarAST t : allRefs) {
Expand All @@ -226,7 +237,7 @@ public Set<Decl> getDeclsForAllElements(List<AltAST> altASTs) {
List<Decl> d = getDeclForAltElement(t,
refLabelName,
needsList.contains(refLabelName),
optional.contains(refLabelName));
!nonOptional.contains(refLabelName));
decls.addAll(d);
}
return decls;
Expand Down

0 comments on commit d706b5d

Please sign in to comment.