Skip to content

Commit 5bf9c77

Browse files
authored
Merge pull request #162 from VariantSync/fix-marlin-macros
Fix marlin macro interpretation
2 parents 19a8518 + a4979e7 commit 5bf9c77

17 files changed

Lines changed: 331 additions & 305 deletions

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,19 @@
22

33
import org.variantsync.diffdetective.datasets.PatchDiffParseOptions;
44
import org.variantsync.diffdetective.datasets.Repository;
5-
import org.variantsync.diffdetective.feature.PreprocessorAnnotationParser;
5+
import org.variantsync.diffdetective.feature.AnnotationParser;
6+
import org.variantsync.diffdetective.feature.cpp.CPPAnnotationParser;
67

78
import java.nio.file.Path;
89

910
/**
1011
* Default repository for Marlin.
1112
*
12-
* @author Kevin Jedelhauser, Paul Maximilian Bittner
13+
* @author Kevin Jedelhauser, Paul Maximilian Bittner, Benjamin Moosherr
1314
*/
1415
public class Marlin {
15-
public static final PreprocessorAnnotationParser ANNOTATION_PARSER =
16-
PreprocessorAnnotationParser.CreateCppAnnotationParser(
17-
new MarlinCPPDiffLineFormulaExtractor()
18-
);
16+
public static final AnnotationParser ANNOTATION_PARSER =
17+
new CPPAnnotationParser(new MarlinControllingCExpressionVisitor());
1918

2019
/**
2120
* 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+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.variantsync.diffdetective.feature;
2+
3+
import org.prop4j.Node;
4+
5+
/**
6+
* Represents a new annotation (i.e., a change in the presence condition).
7+
* This includes, {@link AnnotationType#If adding to the presence condition},
8+
* {@link AnnotationType#Endif removing the most recent formula}
9+
* and {@link AnnotationType others}.
10+
*
11+
* @param type the type of this annotation
12+
* @param formula the formula associated to {@code type}.
13+
* Non-null iff {@link AnnotationType#requiresFormula type.requiresFormula}.
14+
*/
15+
public record Annotation(
16+
AnnotationType type,
17+
Node formula
18+
) {
19+
public Annotation(AnnotationType type, Node formula) {
20+
this.type = type;
21+
this.formula = formula;
22+
23+
if (type.requiresFormula && formula == null) {
24+
throw new IllegalArgumentException("Annotations of type " + type.name + " but got null");
25+
}
26+
if (!type.requiresFormula && formula != null) {
27+
throw new IllegalArgumentException("Annotations of type " + type.name + " do not accept a formula but it was given " + formula);
28+
}
29+
}
30+
31+
/**
32+
* Equivalent to {@link #Annotation(AnnotationType, Node) Annotation(type, null)}.
33+
* Hence, only useable iff {@link AnnotationType#requiresFormula !type.requiresFormula}.
34+
*/
35+
public Annotation(AnnotationType type) {
36+
this(type, null);
37+
}
38+
}
Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,23 @@
11
package org.variantsync.diffdetective.feature;
22

3-
import org.prop4j.Node;
43
import org.variantsync.diffdetective.error.UnparseableFormulaException;
54

65
/**
76
* Interface for a parser that analyzes annotations in parsed text. The parser is responsible for determining the type
8-
* of the annotation (see {@link AnnotationType}), and parsing the annotation into a {@link Node}.
7+
* of the annotation (see {@link AnnotationType}), and parsing the annotation into a {@link org.prop4j.Node}.
98
* <p>
109
* See {@link PreprocessorAnnotationParser} for an example of how an implementation of AnnotationParser could look like.
1110
* </p>
1211
*/
1312
public interface AnnotationParser {
1413
/**
15-
* Determine the annotation type for the given piece of text (typically a line of source code).
14+
* Parse the given line as an annotation.
15+
* Note that {@code line} might also be a line in a diff (i.e., preceded by {@code -} or {@code +}).
1616
*
17-
* @param text The text of which the type is determined.
18-
* @return The annotation type of the piece of text.
17+
* @param line that might contain an annotation
18+
* @return the annotation type and the associated formula.
19+
* If {@code line} doesn't contain an annotation, returns {@code Annotation(AnnotationType.NONE)}.
20+
* @throws UnparseableFormulaException if an annotation is detected but it is malformed
1921
*/
20-
AnnotationType determineAnnotationType(String text);
21-
22-
/**
23-
* Parse the condition of the given text containing an annotation (typically a line of source code).
24-
*
25-
* @param text The text containing a conditional annotation
26-
* @return The formula of the condition in the given annotation.
27-
* If no such formula could be extracted, returns a Literal with the line's condition as name.
28-
* @throws UnparseableFormulaException if there is an error while parsing.
29-
*/
30-
Node parseAnnotation(String text) throws UnparseableFormulaException;
22+
Annotation parseAnnotation(String line) throws UnparseableFormulaException;
3123
}

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,39 @@ public enum AnnotationType {
99
* The piece of text (e.g., "#if ...") contains a conditional annotation that starts a new
1010
* annotated subtree in the variation tree.
1111
*/
12-
If("if"),
12+
If("if", true),
1313

1414
/**
1515
* The piece of text (e.g., "#elif ...") contains a conditional annotation which is only checked
1616
* if the conditions of all preceding annotations belonging to the same annotation chain are not fulfilled.
1717
*/
18-
Elif("elif"),
18+
Elif("elif", true),
1919

2020
/**
2121
* The piece of text (e.g., "#else") contains an annotation that marks a subtree as used alternative
2222
* if the condition of the preceding annotation in the same annotation chain is not fulfilled.
2323
*/
24-
Else("else"),
24+
Else("else", false),
2525

2626
/**
2727
* The piece of text (e.g., "#endif") marks the end of an annotation (chain).
2828
*/
29-
Endif("endif"),
29+
Endif("endif", false),
3030

3131
/**
3232
* The piece of text contains no annotation. This usually means that it contains an artifact.
3333
*/
34-
None("NONE");
34+
None("NONE", false);
3535

3636
public final String name;
37+
/**
38+
* Does this type of annotation require a formula?
39+
*/
40+
public final boolean requiresFormula;
3741

38-
AnnotationType(String name) {
42+
AnnotationType(String name, boolean requiresFormula) {
3943
this.name = name;
44+
this.requiresFormula = requiresFormula;
4045
}
4146

4247
/**

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

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

0 commit comments

Comments
 (0)