Skip to content

Commit a4979e7

Browse files
committed
fix: Reinstantiate the macro handling for Marlin
Until 5056de8, the Marlin macros `ENABLED` and `DISABLED` where handled specially to extract more useful feature mappings.
1 parent 326435e commit a4979e7

7 files changed

Lines changed: 88 additions & 70 deletions

File tree

src/main/java/org/variantsync/diffdetective/datasets/predefined/Marlin.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@
1010
/**
1111
* Default repository for Marlin.
1212
*
13-
* @author Kevin Jedelhauser, Paul Maximilian Bittner
13+
* @author Kevin Jedelhauser, Paul Maximilian Bittner, Benjamin Moosherr
1414
*/
1515
public class Marlin {
1616
public static final AnnotationParser ANNOTATION_PARSER =
17-
new CPPAnnotationParser(
18-
// TODO new MarlinCPPDiffLineFormulaExtractor()
19-
);
17+
new CPPAnnotationParser(new MarlinControllingCExpressionVisitor());
2018

2119
/**
2220
* Clones Marlin from Github.

src/main/java/org/variantsync/diffdetective/datasets/predefined/MarlinCPPDiffLineFormulaExtractor.java

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.variantsync.diffdetective.datasets.predefined;
2+
3+
import org.antlr.v4.runtime.tree.TerminalNode;
4+
import org.prop4j.Node;
5+
import org.variantsync.diffdetective.feature.antlr.CExpressionParser;
6+
import org.variantsync.diffdetective.feature.cpp.ControllingCExpressionVisitor;
7+
8+
import java.util.List;
9+
10+
import static org.variantsync.diffdetective.util.fide.FormulaUtils.negate;
11+
12+
/**
13+
* Parses C preprocessor annotations in the marlin firmware.
14+
* <p>
15+
* In contrast to {@link ControllingCExpressionVisitor},
16+
* this class resolves the {@code ENABLED} and {@code DISABLED} macros
17+
* that are used in Marlin to check for features being (de-)selected.
18+
*
19+
* @author Paul Bittner, Benjamin Moosherr
20+
*/
21+
public class MarlinControllingCExpressionVisitor extends ControllingCExpressionVisitor {
22+
@Override
23+
public Node visitPrimaryExpression(CExpressionParser.PrimaryExpressionContext ctx) {
24+
if (ctx.macroExpression() != null) {
25+
TerminalNode name = ctx.macroExpression().Identifier();
26+
List<CExpressionParser.AssignmentExpressionContext> arguments = ctx.macroExpression().argumentExpressionList().assignmentExpression();
27+
28+
if (arguments.size() == 1) {
29+
if (name.getText().equals("ENABLED")) {
30+
return abstractToLiteral(arguments.get(0));
31+
}
32+
if (name.getText().equals("DISABLED")) {
33+
return negate(abstractToLiteral(arguments.get(0)));
34+
}
35+
}
36+
}
37+
38+
return super.visitPrimaryExpression(ctx);
39+
}
40+
}

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

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

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ public class CPPAnnotationParser extends PreprocessorAnnotationParser {
3131
private static final String CPP_ANNOTATION_REGEX = "^[+-]?\\s*#\\s*(?<directive>if|ifdef|ifndef|elif|elifdef|elifndef|else|endif)(?<formula>[\\s(].*)?$";
3232
private static final Pattern CPP_ANNOTATION_PATTERN = Pattern.compile(CPP_ANNOTATION_REGEX);
3333

34-
public CPPAnnotationParser() {
34+
private ParseTreeVisitor<Node> formulaVisitor;
35+
36+
public CPPAnnotationParser(ParseTreeVisitor<Node> formulaVisitor) {
3537
super(CPP_ANNOTATION_PATTERN);
38+
this.formulaVisitor = formulaVisitor;
39+
}
40+
41+
public CPPAnnotationParser() {
42+
this(new ControllingCExpressionVisitor());
3643
}
3744

3845
@Override
@@ -45,7 +52,7 @@ public Node parseFormula(final String directive, final String formula) throws Un
4552
CExpressionParser parser = new CExpressionParser(tokens);
4653
parser.addErrorListener(new ParseErrorListener(formula));
4754

48-
parsedFormula = parser.expression().accept(new ControllingCExpressionVisitor());
55+
parsedFormula = parser.expression().accept(formulaVisitor);
4956
} catch (UncheckedUnparseableFormulaException e) {
5057
throw e.inner();
5158
} catch (Exception e) {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public Node visitLogicalOperand(CExpressionParser.LogicalOperandContext ctx) {
275275
// logicalOrExpression
276276
// : logicalAndExpression ( '||' logicalAndExpression)*
277277
// ;
278-
private Node visitLogicalExpression(ParserRuleContext expressionContext, Function<Node[], Node> newLogicNode) {
278+
protected Node visitLogicalExpression(ParserRuleContext expressionContext, Function<Node[], Node> newLogicNode) {
279279
if (expressionContext.getChildCount() == 1) {
280280
return expressionContext.getChild(0).accept(this);
281281
} else {
@@ -291,7 +291,7 @@ private Node visitLogicalExpression(ParserRuleContext expressionContext, Functio
291291
}
292292
}
293293

294-
private Node recurseOnSingleChild(ParserRuleContext ctx) {
294+
protected Node recurseOnSingleChild(ParserRuleContext ctx) {
295295
if (ctx.getChildCount() > 1) {
296296
// We have to abstract the expression if there is more than one operand
297297
return abstractToLiteral(ctx);
@@ -301,7 +301,7 @@ private Node recurseOnSingleChild(ParserRuleContext ctx) {
301301
}
302302
}
303303

304-
private Node abstractToLiteral(ParserRuleContext ctx) {
304+
protected Node abstractToLiteral(ParserRuleContext ctx) {
305305
return var(ctx.accept(abstractingVisitor).toString());
306306
}
307307
}

src/test/java/CPPParserTest.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import org.junit.jupiter.params.ParameterizedTest;
22
import org.junit.jupiter.params.provider.MethodSource;
33
import org.prop4j.Node;
4+
import org.variantsync.diffdetective.datasets.predefined.MarlinControllingCExpressionVisitor;
45
import org.variantsync.diffdetective.error.UnparseableFormulaException;
56
import org.variantsync.diffdetective.feature.Annotation;
67
import org.variantsync.diffdetective.feature.AnnotationType;
@@ -140,6 +141,28 @@ private static List<TestCase> testCases() {
140141
);
141142
}
142143

144+
private static List<TestCase> nonMarlinTestCases() {
145+
return List.of(
146+
new TestCase("#if ENABLED(A)", var("ENABLED(A)")),
147+
new TestCase("#if DISABLED(A)", var("DISABLED(A)")),
148+
new TestCase("#if ENABLED(FEATURE_A) && DISABLED(FEATURE_B)", and(var("ENABLED(FEATURE_A)"), var("DISABLED(FEATURE_B)"))),
149+
new TestCase("#if ENABLED(A, B)", var("ENABLED(A,B)")),
150+
new TestCase("#if OTHER(A, B)", var("OTHER(A,B)")),
151+
new TestCase("#if A", var("A"))
152+
);
153+
}
154+
155+
private static List<TestCase> marlinTestCases() {
156+
return List.of(
157+
new TestCase("#if ENABLED(A)", var("A")),
158+
new TestCase("#if DISABLED(A)", negate(var("A"))),
159+
new TestCase("#if ENABLED(FEATURE_A) && DISABLED(FEATURE_B)", and(var("FEATURE_A"), negate(var("FEATURE_B")))),
160+
new TestCase("#if ENABLED(A, B)", var("ENABLED(A,B)")),
161+
new TestCase("#if OTHER(A, B)", var("OTHER(A,B)")),
162+
new TestCase("#if A", var("A"))
163+
);
164+
}
165+
143166
private static List<ThrowingTestCase> throwingTestCases() {
144167
return List.of(
145168
// Empty formula
@@ -150,14 +173,24 @@ private static List<ThrowingTestCase> throwingTestCases() {
150173
}
151174

152175
@ParameterizedTest
153-
@MethodSource("testCases")
176+
@MethodSource({"testCases", "nonMarlinTestCases"})
154177
public void testCase(TestCase testCase) throws UnparseableFormulaException {
155178
assertEquals(
156179
testCase.expectedAnnotation(),
157180
new CPPAnnotationParser().parseAnnotation(testCase.formula())
158181
);
159182
}
160183

184+
@ParameterizedTest
185+
@MethodSource({"testCases", "marlinTestCases"})
186+
public void marlinTestCase(TestCase testCase) throws UnparseableFormulaException {
187+
assertEquals(
188+
testCase.expectedAnnotation(),
189+
new CPPAnnotationParser(new MarlinControllingCExpressionVisitor()).parseAnnotation(testCase.formula())
190+
);
191+
}
192+
193+
161194
@ParameterizedTest
162195
@MethodSource("throwingTestCases")
163196
public void throwingTestCase(ThrowingTestCase testCase) {

0 commit comments

Comments
 (0)