diff --git a/src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/BasicRecoveryTests.rsc b/src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/BasicRecoveryTests.rsc index 692bf97f308..f3cc13aacdd 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/BasicRecoveryTests.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/concrete/recovery/BasicRecoveryTests.rsc @@ -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; -} diff --git a/src/org/rascalmpl/library/util/ErrorRecovery.java b/src/org/rascalmpl/library/util/ErrorRecovery.java index d117a59d717..5d116f0e70e 100644 --- a/src/org/rascalmpl/library/util/ErrorRecovery.java +++ b/src/org/rascalmpl/library/util/ErrorRecovery.java @@ -48,17 +48,17 @@ public ScoredTree(IConstructor tree, int score) { */ 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 processedTrees) { + private ScoredTree disambiguate(IConstructor tree, boolean allowAmbiguity, boolean buildTree, Map 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); @@ -67,7 +67,7 @@ private ScoredTree disambiguate(IConstructor tree, boolean allowAmbiguity, Map processedTrees) { + private ScoredTree disambiguateAppl(ITree appl, boolean allowAmbiguity, boolean buildTree, Map processedTrees) { ScoredTree result = processedTrees.get(appl); if (result != null) { return result; @@ -83,9 +83,9 @@ private ScoredTree disambiguateAppl(ITree appl, boolean allowAmbiguity, Map processedTrees) { + private ScoredTree disambiguateAmb(ITree amb, boolean allowAmbiguity, boolean buildTree, Map processedTrees) { ScoredTree result = processedTrees.get(amb); if (result != null) { return result; @@ -124,9 +124,10 @@ private ScoredTree disambiguateAmb(ITree amb, boolean allowAmbiguity, Map 1 && !allowAmbiguity) { // We have an ambiguity between non-error trees - if (!allowAmbiguity) { - throw new Ambiguous(resultTree); + resultTree = rascalValues.amb(remainingAlts); + throw new Ambiguous(resultTree); + } + + if (buildTree) { + 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); } } @@ -217,4 +222,8 @@ private void collectAmbErrors(ITree amb, IListWriter errors, Set p collectErrors((ITree) alt, errors, processedTrees); } } + + public void checkForRegularAmbiguities(IConstructor parseForest) { + disambiguate(parseForest, false, false, new HashMap<>()); + } } diff --git a/src/org/rascalmpl/library/util/ErrorRecovery.rsc b/src/org/rascalmpl/library/util/ErrorRecovery.rsc index 08673830a91..a570cdcf2e4 100644 --- a/src/org/rascalmpl/library/util/ErrorRecovery.rsc +++ b/src/org/rascalmpl/library/util/ErrorRecovery.rsc @@ -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); }; diff --git a/src/org/rascalmpl/values/RascalFunctionValueFactory.java b/src/org/rascalmpl/values/RascalFunctionValueFactory.java index 6c4b1ba871f..3bf66e83c73 100644 --- a/src/org/rascalmpl/values/RascalFunctionValueFactory.java +++ b/src/org/rascalmpl/values/RascalFunctionValueFactory.java @@ -585,10 +585,10 @@ private ITree parseObject(String methodName, ISourceLocation location, char[] in } 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); } return parseForest;