Skip to content

Commit dd46fb8

Browse files
committed
Inline and remove AbstractingFormulaExtractor
This class is weirdly coupled with its subclasses. It uses a regex and assumes that some arbitrary groups exist and have the correct meaning. Furthermore, the exception handling handles UncheckedUnParseableFormulaException specially which should also be an implementation detail of the code that actually throws it. Last but not least, it only saves redundant exception handling code (which is dependent on the subclass) as the matching code has to be repeated by CPPDiffLineFormulaExtractor anyways (also degrading performance as the regex needs to be matched twice for no reason).
1 parent 8fde557 commit dd46fb8

3 files changed

Lines changed: 58 additions & 119 deletions

File tree

src/main/java/org/variantsync/diffdetective/feature/AbstractingFormulaExtractor.java

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/main/java/org/variantsync/diffdetective/feature/cpp/CPPDiffLineFormulaExtractor.java

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
import org.antlr.v4.runtime.CommonTokenStream;
55
import org.prop4j.Node;
66
import org.prop4j.Not;
7+
import org.tinylog.Logger;
8+
import org.variantsync.diffdetective.error.UncheckedUnParseableFormulaException;
79
import org.variantsync.diffdetective.error.UnparseableFormulaException;
8-
import org.variantsync.diffdetective.feature.AbstractingFormulaExtractor;
10+
import org.variantsync.diffdetective.feature.DiffLineFormulaExtractor;
911
import org.variantsync.diffdetective.feature.ParseErrorListener;
1012
import org.variantsync.diffdetective.feature.antlr.CExpressionLexer;
1113
import org.variantsync.diffdetective.feature.antlr.CExpressionParser;
@@ -22,15 +24,11 @@
2224
*
2325
* @author Paul Bittner, Sören Viegener, Benjamin Moosherr, Alexander Schultheiß
2426
*/
25-
public class CPPDiffLineFormulaExtractor extends AbstractingFormulaExtractor {
27+
public class CPPDiffLineFormulaExtractor implements DiffLineFormulaExtractor {
2628
// ^[+-]?\s*#\s*(if|ifdef|ifndef|elif)(\s+(.*)|\((.*)\))$
2729
private static final String CPP_ANNOTATION_REGEX = "^[+-]?\\s*#\\s*(if|ifdef|ifndef|elif)([\\s(].*)$";
2830
private static final Pattern CPP_ANNOTATION_PATTERN = Pattern.compile(CPP_ANNOTATION_REGEX);
2931

30-
public CPPDiffLineFormulaExtractor() {
31-
super(CPP_ANNOTATION_PATTERN);
32-
}
33-
3432
/**
3533
* Extracts and parses the feature formula from a macro line (possibly within a diff).
3634
*
@@ -39,38 +37,36 @@ public CPPDiffLineFormulaExtractor() {
3937
*/
4038
@Override
4139
public Node extractFormula(final String line) throws UnparseableFormulaException {
42-
// Delegate the formula extraction to AbstractingFormulaExtractor
43-
Node fm = super.extractFormula(line);
44-
45-
// negate for ifndef
40+
// Match the formula from the macro line
4641
final Matcher matcher = CPP_ANNOTATION_PATTERN.matcher(line);
47-
if (matcher.find() && "ifndef".equals(matcher.group(1))) {
48-
fm = new Not(fm);
42+
if (!matcher.find()) {
43+
throw new UnparseableFormulaException("Could not extract formula from line \"" + line + "\".");
4944
}
45+
String annotationType = matcher.group(1);
46+
String formula = matcher.group(2);
5047

51-
return fm;
52-
}
48+
// abstract complex formulas (e.g., if they contain arithmetics or macro calls)
49+
Node parsedFormula;
50+
try {
51+
CExpressionLexer lexer = new CExpressionLexer(CharStreams.fromString(formula));
52+
CommonTokenStream tokens = new CommonTokenStream(lexer);
5353

54-
/**
55-
* Abstract the given formula.
56-
* <p>
57-
* First, the visitor uses ANTLR to parse the formula into a parse tree gives the tree to a {@link ControllingCExpressionVisitor}.
58-
* The visitor traverses the tree starting from the root, searching for subtrees that must be abstracted.
59-
* If such a subtree is found, the visitor calls an {@link AbstractingCExpressionVisitor} to abstract the part of
60-
* the formula in the subtree.
61-
* </p>
62-
*
63-
* @param formula that is to be abstracted
64-
* @return the abstracted formula
65-
*/
66-
@Override
67-
protected Node abstractFormula(String formula) {
68-
CExpressionLexer lexer = new CExpressionLexer(CharStreams.fromString(formula));
69-
CommonTokenStream tokens = new CommonTokenStream(lexer);
54+
CExpressionParser parser = new CExpressionParser(tokens);
55+
parser.addErrorListener(new ParseErrorListener(formula));
56+
57+
parsedFormula = parser.expression().accept(new ControllingCExpressionVisitor());
58+
} catch (UncheckedUnParseableFormulaException e) {
59+
throw e.inner();
60+
} catch (Exception e) {
61+
Logger.warn(e);
62+
throw new UnparseableFormulaException(e);
63+
}
7064

71-
CExpressionParser parser = new CExpressionParser(tokens);
72-
parser.addErrorListener(new ParseErrorListener(formula));
65+
// negate for ifndef
66+
if ("ifndef".equals(annotationType)) {
67+
parsedFormula = new Not(parsedFormula);
68+
}
7369

74-
return parser.expression().accept(new ControllingCExpressionVisitor());
70+
return parsedFormula;
7571
}
7672
}

src/main/java/org/variantsync/diffdetective/feature/jpp/JPPDiffLineFormulaExtractor.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
import org.antlr.v4.runtime.CommonTokenStream;
55
import org.antlr.v4.runtime.tree.ParseTree;
66
import org.prop4j.Node;
7-
import org.variantsync.diffdetective.feature.AbstractingFormulaExtractor;
7+
import org.tinylog.Logger;
8+
import org.variantsync.diffdetective.error.UncheckedUnParseableFormulaException;
9+
import org.variantsync.diffdetective.error.UnparseableFormulaException;
10+
import org.variantsync.diffdetective.feature.DiffLineFormulaExtractor;
811
import org.variantsync.diffdetective.feature.ParseErrorListener;
912
import org.variantsync.diffdetective.feature.antlr.JPPExpressionLexer;
1013
import org.variantsync.diffdetective.feature.antlr.JPPExpressionParser;
1114

15+
import java.util.regex.Matcher;
1216
import java.util.regex.Pattern;
1317

1418
/**
@@ -20,14 +24,10 @@
2024
*
2125
* @author Alexander Schultheiß
2226
*/
23-
public class JPPDiffLineFormulaExtractor extends AbstractingFormulaExtractor {
27+
public class JPPDiffLineFormulaExtractor implements DiffLineFormulaExtractor {
2428
private static final String JPP_ANNOTATION_REGEX = "^[+-]?\\s*//\\s*#\\s*(if|elif)([\\s(].*)$";
2529
private static final Pattern JPP_ANNOTATION_PATTERN = Pattern.compile(JPP_ANNOTATION_REGEX);
2630

27-
public JPPDiffLineFormulaExtractor() {
28-
super(JPP_ANNOTATION_PATTERN);
29-
}
30-
3131
/**
3232
* Abstract the given formula.
3333
* <p>
@@ -36,16 +36,31 @@ public JPPDiffLineFormulaExtractor() {
3636
* If such a subtree is found, the visitor abstracts the part of the formula in the subtree.
3737
* </p>
3838
*
39-
* @param formula that is to be abstracted
39+
* @param line that contains the formula to be abstracted
4040
* @return the abstracted formula
4141
*/
4242
@Override
43-
protected Node abstractFormula(String formula) {
44-
JPPExpressionLexer lexer = new JPPExpressionLexer(CharStreams.fromString(formula));
45-
CommonTokenStream tokens = new CommonTokenStream(lexer);
46-
JPPExpressionParser parser = new JPPExpressionParser(tokens);
47-
parser.addErrorListener(new ParseErrorListener(formula));
48-
ParseTree tree = parser.expression();
49-
return tree.accept(new ControllingJPPExpressionVisitor());
43+
public Node extractFormula(final String line) throws UnparseableFormulaException {
44+
// Match the formula from the macro line
45+
final Matcher matcher = JPP_ANNOTATION_PATTERN.matcher(line);
46+
if (!matcher.find()) {
47+
throw new UnparseableFormulaException("Could not extract formula from line \"" + line + "\".");
48+
}
49+
String formula = matcher.group(2);
50+
51+
// abstract complex formulas (e.g., if they contain arithmetics or macro calls)
52+
try {
53+
JPPExpressionLexer lexer = new JPPExpressionLexer(CharStreams.fromString(formula));
54+
CommonTokenStream tokens = new CommonTokenStream(lexer);
55+
JPPExpressionParser parser = new JPPExpressionParser(tokens);
56+
parser.addErrorListener(new ParseErrorListener(formula));
57+
ParseTree tree = parser.expression();
58+
return tree.accept(new ControllingJPPExpressionVisitor());
59+
} catch (UncheckedUnParseableFormulaException e) {
60+
throw e.inner();
61+
} catch (Exception e) {
62+
Logger.warn(e);
63+
throw new UnparseableFormulaException(e);
64+
}
5065
}
5166
}

0 commit comments

Comments
 (0)