Skip to content

Commit

Permalink
made field projection in parse trees robust against parse error trees
Browse files Browse the repository at this point in the history
  • Loading branch information
jurgenvinju committed Nov 8, 2024
1 parent 415773f commit bb7ea53
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/org/rascalmpl/values/parsetrees/ProductionAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.rascalmpl.values.parsetrees;

import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.IInteger;
import io.usethesource.vallang.IList;
import io.usethesource.vallang.IListWriter;
import io.usethesource.vallang.INode;
Expand Down Expand Up @@ -206,4 +207,12 @@ public static boolean shouldFlatten(IConstructor surrounding, IConstructor neste
}
return false;
}

public static int getErrorDot(IConstructor prod) {
return ((IInteger) prod.get("dot")).intValue();

Check warning on line 212 in src/org/rascalmpl/values/parsetrees/ProductionAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/ProductionAdapter.java#L212

Added line #L212 was not covered by tests
}

public static IConstructor getErrorProd(IConstructor prod) {
return (IConstructor) prod.get("prod");

Check warning on line 216 in src/org/rascalmpl/values/parsetrees/ProductionAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/ProductionAdapter.java#L216

Added line #L216 was not covered by tests
}
}
39 changes: 39 additions & 0 deletions src/org/rascalmpl/values/parsetrees/TreeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.fusesource.jansi.Ansi.Color;
import org.rascalmpl.exceptions.ImplementationError;
import org.rascalmpl.interpreter.utils.LimitedResultWriter;
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.RascalValueFactory;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.parsetrees.visitors.TreeVisitor;
Expand Down Expand Up @@ -139,6 +140,9 @@ public static IConstructor getProduction(ITree tree) {
/**
* This function assumes that getLabeledField does not return null for the same parameters!
*/
// TODO @PieterOlivier I guess we could extend this the way we also extended the getLabeledField.
// if the field is still on the parsed side of the dot then we're fine. Otherwise we could
// think about shifting the dot if we put in correct trees at the right places?
public static ITree putLabeledField(ITree tree, String field, ITree repl) {
if (isAppl(tree)) {
IConstructor prod = TreeAdapter.getProduction(tree);
Expand Down Expand Up @@ -266,6 +270,41 @@ else if (ProductionAdapter.isRegular(prod)) {
return null;
}
}
else if (ProductionAdapter.isError(prod)) {
int dot = ProductionAdapter.getErrorDot(prod);
IConstructor eprod = ProductionAdapter.getErrorProd(prod);
IList syms = ProductionAdapter.getSymbols(eprod);
int index = SymbolAdapter.indexOfLabel(syms, field);

Check warning on line 277 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L274-L277

Added lines #L274 - L277 were not covered by tests

if (index != -1) {
IConstructor sym = (IConstructor) syms.get(index);
sym = SymbolAdapter.stripLabelsAndConditions(sym);

Check warning on line 281 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L280-L281

Added lines #L280 - L281 were not covered by tests

if (dot <= index) {
// we have parsed the field so we can just return it.
// this is a likely scenario
return new FieldResult(sym, (ITree) tree.getArgs().get(index));

Check warning on line 286 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L286

Added line #L286 was not covered by tests
}
else {
// We have the right prodction and the field would be there, if we didn't recover from a parse error
// and are missing some of the children (including the indicated field).
// So we return a quasi tree that is of the right type, but it otherwise just an error tree
// like its parent. This tree does not have content, because we wouldn't know which of the skipped
// parts are meant.
var vf = IRascalValueFactory.getInstance();

Check warning on line 294 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L294

Added line #L294 was not covered by tests
// @PieterOlivier is this the right way to do this? I just need an empty tree of the right symbol.
var skipped = vf.constructor(RascalValueFactory.Production_Skipped);
var skippedProd = vf.constructor(RascalValueFactory.Production_Error, sym, skipped, vf.integer(0));
var skippedTree = vf.appl(skippedProd);
var parentLoc = getLocation(tree);

Check warning on line 299 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L296-L299

Added lines #L296 - L299 were not covered by tests
if (parentLoc != null) {
// TODO @PieterOlivier I guess we need the location of the last parsed element, and use an
// empty range that is just beyond that. But for now I'd like to test with this.
}
return new FieldResult(sym, skippedTree);

Check warning on line 304 in src/org/rascalmpl/values/parsetrees/TreeAdapter.java

View check run for this annotation

Codecov / codecov/patch

src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L304

Added line #L304 was not covered by tests
}
}
}
}

return null;
Expand Down

0 comments on commit bb7ea53

Please sign in to comment.