Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/remove auto disambiguation #2075

Merged
merged 3 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,3 @@ test bool basicOk() = checkRecovery(#S, "a b c $", []);
test bool abx() = checkRecovery(#S, "a b x $", ["x "]);

test bool axc() = checkRecovery(#S, "a x c $", ["x c"]);

test bool autoDisambiguation() {
str input = "a x $";

assert checkRecovery(#S, input, ["x "]);

Tree autoDisambiguated = parser(#S, allowRecovery=true, allowAmbiguity=false)(input, |unknown:///|);
return size(findAllErrors(autoDisambiguated)) == 1;
}
55 changes: 32 additions & 23 deletions src/org/rascalmpl/library/util/ErrorRecovery.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@
*/

public IConstructor disambiguateErrors(IConstructor arg, IBool allowAmbiguity) {
return disambiguate(arg, allowAmbiguity.getValue(), new HashMap<>()).tree;
return disambiguate(arg, allowAmbiguity.getValue(), true, new HashMap<>()).tree;
}

private ScoredTree disambiguate(IConstructor tree, boolean allowAmbiguity, Map<IConstructor, ScoredTree> processedTrees) {
private ScoredTree disambiguate(IConstructor tree, boolean allowAmbiguity, boolean buildTree, Map<IConstructor, ScoredTree> processedTrees) {
Type type = tree.getConstructorType();
ScoredTree result;

if (type == RascalValueFactory.Tree_Appl) {
result = disambiguateAppl((ITree) tree, allowAmbiguity, processedTrees);
result = disambiguateAppl((ITree) tree, allowAmbiguity, buildTree, processedTrees);
} else if (type == RascalValueFactory.Tree_Amb) {
result = disambiguateAmb((ITree) tree, allowAmbiguity, processedTrees);
result = disambiguateAmb((ITree) tree, allowAmbiguity, buildTree, processedTrees);
} else {
// Other trees (cycle, char) do not have subtrees so they have a score of 0
result = new ScoredTree(tree, 0);
Expand All @@ -67,7 +67,7 @@
return result;
}

private ScoredTree disambiguateAppl(ITree appl, boolean allowAmbiguity, Map<IConstructor, ScoredTree> processedTrees) {
private ScoredTree disambiguateAppl(ITree appl, boolean allowAmbiguity, boolean buildTree, Map<IConstructor, ScoredTree> processedTrees) {
ScoredTree result = processedTrees.get(appl);
if (result != null) {
return result;
Expand All @@ -83,9 +83,9 @@
// Disambiguate and score all children
for (int i=0; i<args.size(); i++) {
IValue arg = args.get(i);
ScoredTree disambiguatedArg = disambiguate((IConstructor) arg, allowAmbiguity, processedTrees);
ScoredTree disambiguatedArg = disambiguate((IConstructor) arg, allowAmbiguity, buildTree, processedTrees);
totalScore += disambiguatedArg.score;
if (disambiguatedArg.tree != arg && disambiguatedArgs == null) {
if (buildTree && disambiguatedArg.tree != arg && disambiguatedArgs == null) {
disambiguatedArgs = rascalValues.listWriter();
for (int j=0; j<i; j++) {
disambiguatedArgs.append(args.get(j));
Expand All @@ -98,11 +98,11 @@
}

// Only build a new tree if at least one of the arguments has changed
ITree resultTree;
ITree resultTree = null;
if (disambiguatedArgs != null) {
// Some arguments have changed
resultTree = TreeAdapter.setArgs(appl, disambiguatedArgs.done());
} else {
} else if (buildTree) {
// None of the arguments have changed
resultTree = appl;
}
Expand All @@ -115,7 +115,7 @@
return result;
}

private ScoredTree disambiguateAmb(ITree amb, boolean allowAmbiguity, Map<IConstructor, ScoredTree> processedTrees) {
private ScoredTree disambiguateAmb(ITree amb, boolean allowAmbiguity, boolean buildTree, Map<IConstructor, ScoredTree> processedTrees) {
ScoredTree result = processedTrees.get(amb);
if (result != null) {
return result;
Expand All @@ -124,9 +124,10 @@
ISet originalAlts = (ISet) amb.get(0);

ISetWriter alternativesWithoutErrors = null;

ScoredTree errorAltWithBestScore = null;
for (IValue alt : originalAlts) {
ScoredTree disambiguatedAlt = disambiguate((IConstructor) alt, allowAmbiguity, processedTrees);
ScoredTree disambiguatedAlt = disambiguate((IConstructor) alt, allowAmbiguity, buildTree, processedTrees);
if (disambiguatedAlt.score == 0) {
// Non-error tree
if (alternativesWithoutErrors == null) {
Expand All @@ -149,20 +150,24 @@

ISet remainingAlts = alternativesWithoutErrors.done();

ITree resultTree;
if (remainingAlts.size() == originalAlts.size()) {
// All children are without errors, return the original tree
resultTree = amb;
} else if (remainingAlts.size() == 1) {
// One child without errors remains, dissolve the amb tree
resultTree = (ITree) remainingAlts.iterator().next();
} else {
// Create a new amb tree with the remaining non-error trees
resultTree = rascalValues.amb(remainingAlts);
ITree resultTree = null;

if (remainingAlts.size() > 1 && !allowAmbiguity) {
// We have an ambiguity between non-error trees
if (!allowAmbiguity) {
throw new Ambiguous(resultTree);
resultTree = rascalValues.amb(remainingAlts);
throw new Ambiguous(resultTree);

Check warning on line 158 in src/org/rascalmpl/library/util/ErrorRecovery.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/util/ErrorRecovery.java#L157-L158

Added lines #L157 - L158 were not covered by tests
}

if (buildTree) {
if (remainingAlts.size() == originalAlts.size()) {
// All children are without errors, return the original tree
resultTree = amb;

Check warning on line 164 in src/org/rascalmpl/library/util/ErrorRecovery.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/util/ErrorRecovery.java#L164

Added line #L164 was not covered by tests
} else if (remainingAlts.size() == 1) {
// One child without errors remains, dissolve the amb tree
resultTree = (ITree) remainingAlts.iterator().next();
} else {
// Create a new amb tree with the remaining non-error trees
resultTree = rascalValues.amb(remainingAlts);

Check warning on line 170 in src/org/rascalmpl/library/util/ErrorRecovery.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/util/ErrorRecovery.java#L170

Added line #L170 was not covered by tests
}
}

Expand Down Expand Up @@ -217,4 +222,8 @@
collectErrors((ITree) alt, errors, processedTrees);
}
}

public void checkForRegularAmbiguities(IConstructor parseForest) {
disambiguate(parseForest, false, false, new HashMap<>());
}

Check warning on line 228 in src/org/rascalmpl/library/util/ErrorRecovery.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/library/util/ErrorRecovery.java#L227-L228

Added lines #L227 - L228 were not covered by tests
}
3 changes: 3 additions & 0 deletions src/org/rascalmpl/library/util/ErrorRecovery.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ This filter removes error trees until no ambiguities caused by error recovery ar
Note that regular ambiguous trees remain in the parse forest unless `allowAmbiguity` is set to false in which case an error is thrown.
}
java Tree disambiguateErrors(Tree t, bool allowAmbiguity=true);

Tree(Tree) createErrorFilter(bool allowAmbiguity) =
Tree(Tree t) { return disambiguateErrors(t, allowAmbiguity=allowAmbiguity); };
6 changes: 3 additions & 3 deletions src/org/rascalmpl/values/RascalFunctionValueFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,10 @@
}
ITree parseForest = (ITree) parserInstance.parse(methodName, uri, input, exec, new DefaultNodeFlattener<>(), new UPTRNodeFactory(allowRecovery || allowAmbiguity), recoverer, debugListener);

if (!allowAmbiguity && allowRecovery && filters.isEmpty()) {
// Filter error-induced ambiguities
if (!allowAmbiguity && allowRecovery) {
// Check for 'regular' (non-error) ambiguities
RascalValueFactory valueFactory = (RascalValueFactory) ValueFactoryFactory.getValueFactory();
parseForest = (ITree) new ErrorRecovery(valueFactory).disambiguateErrors(parseForest, valueFactory.bool(false));
new ErrorRecovery(valueFactory).checkForRegularAmbiguities(parseForest);

Check warning on line 591 in src/org/rascalmpl/values/RascalFunctionValueFactory.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/RascalFunctionValueFactory.java#L591

Added line #L591 was not covered by tests
}

return parseForest;
Expand Down
Loading