11package org .variantsync .diffdetective .feature .cpp ;
22
3- import org .antlr .v4 .runtime .*;
4- import org .antlr .v4 .runtime .atn .ATNConfigSet ;
5- import org .antlr .v4 .runtime .dfa .DFA ;
6- import org .antlr .v4 .runtime .tree .ParseTree ;
7- import org .tinylog .Logger ;
8- import org .variantsync .diffdetective .error .UncheckedUnParseableFormulaException ;
3+ import org .antlr .v4 .runtime .CharStreams ;
4+ import org .antlr .v4 .runtime .CommonTokenStream ;
95import org .variantsync .diffdetective .error .UnparseableFormulaException ;
6+ import org .variantsync .diffdetective .feature .AbstractingFormulaExtractor ;
7+ import org .variantsync .diffdetective .feature .ParseErrorListener ;
108import org .variantsync .diffdetective .feature .antlr .CExpressionLexer ;
119import org .variantsync .diffdetective .feature .antlr .CExpressionParser ;
1210
13- import java .util .BitSet ;
14- import java .util .function .Supplier ;
1511import java .util .regex .Matcher ;
1612import java .util .regex .Pattern ;
1713
2218 * (Other annotations do not have expressions.)
2319 * The given pre-processor statement might also a line in a diff (i.e., preceeded by a - or +).
2420 *
25- * @author Paul Bittner, Sören Viegener, Benjamin Moosherr
21+ * @author Paul Bittner, Sören Viegener, Benjamin Moosherr, Alexander Schultheiß
2622 */
27- public class CPPDiffLineFormulaExtractor {
23+ public class CPPDiffLineFormulaExtractor extends AbstractingFormulaExtractor {
2824 // ^[+-]?\s*#\s*(if|ifdef|ifndef|elif)(\s+(.*)|\((.*)\))$
2925 private static final String CPP_ANNOTATION_REGEX = "^[+-]?\\ s*#\\ s*(if|ifdef|ifndef|elif)(\\ s+(.*)|(\\ (.*\\ )))$" ;
30- private static final Pattern CPP_ANNOTATION_REGEX_PATTERN = Pattern .compile (CPP_ANNOTATION_REGEX );
26+ private static final Pattern CPP_ANNOTATION_PATTERN = Pattern .compile (CPP_ANNOTATION_REGEX );
3127
32- /**
33- * Resolves any macros in the given formula that are relevant for feature annotations.
34- * For example, in {@link org.variantsync.diffdetective.datasets.predefined.MarlinCPPDiffLineFormulaExtractor Marlin},
35- * feature annotations are given by the custom <code>ENABLED</code> and <code>DISABLED</code> macros,
36- * which have to be unwrapped.
37- *
38- * @param formula The formula whose feature macros to resolve.
39- * @return The parseable formula as string. The default implementation returns the input string.
40- */
41- protected String resolveFeatureMacroFunctions (String formula ) {
42- return formula ;
28+ public CPPDiffLineFormulaExtractor () {
29+ super (CPP_ANNOTATION_PATTERN );
4330 }
4431
4532 /**
@@ -48,39 +35,14 @@ protected String resolveFeatureMacroFunctions(String formula) {
4835 * @param line The line of which to get the feature mapping
4936 * @return The feature mapping as a String of the given line
5037 */
38+ @ Override
5139 public String extractFormula (final String line ) throws UnparseableFormulaException {
52- final Matcher matcher = CPP_ANNOTATION_REGEX_PATTERN .matcher (line );
53- final Supplier <UnparseableFormulaException > couldNotExtractFormula = () ->
54- new UnparseableFormulaException ("Could not extract formula from line \" " + line + "\" ." );
55-
56- // Retrieve the formula from the macro line
57- String fm ;
58- if (matcher .find ()) {
59- if (matcher .group (3 ) != null ) {
60- fm = matcher .group (3 );
61- } else {
62- fm = matcher .group (4 );
63- }
64- } else {
65- throw couldNotExtractFormula .get ();
66- }
67-
68- // abstract complex formulas (e.g., if they contain arithmetics or macro calls)
69- try {
70- fm = abstractFormula (fm );
71- } catch (UncheckedUnParseableFormulaException e ) {
72- throw e .inner ();
73- } catch (Exception e ) {
74- Logger .warn (e );
75- throw new UnparseableFormulaException (e );
76- }
77-
78- if (fm .isEmpty ()) {
79- throw couldNotExtractFormula .get ();
80- }
40+ // Delegate the formula extraction to AbstractingFormulaExtractor
41+ String fm = super .extractFormula (line );
8142
8243 // negate for ifndef
83- if ("ifndef" .equals (matcher .group (1 ))) {
44+ final Matcher matcher = CPP_ANNOTATION_PATTERN .matcher (line );
45+ if (matcher .find () && "ifndef" .equals (matcher .group (1 ))) {
8446 fm = "!(" + fm + ")" ;
8547 }
8648
@@ -99,31 +61,14 @@ public String extractFormula(final String line) throws UnparseableFormulaExcepti
9961 * @param formula that is to be abstracted
10062 * @return the abstracted formula
10163 */
102- private String abstractFormula (String formula ) {
64+ @ Override
65+ protected String abstractFormula (String formula ) {
10366 CExpressionLexer lexer = new CExpressionLexer (CharStreams .fromString (formula ));
10467 CommonTokenStream tokens = new CommonTokenStream (lexer );
105- CExpressionParser parser = new CExpressionParser (tokens );
106- parser .addErrorListener (new ANTLRErrorListener () {
107- @ Override
108- public void syntaxError (Recognizer <?, ?> recognizer , Object o , int i , int i1 , String s , RecognitionException e ) {
109- Logger .warn ("syntax error: {} ; {}" , s , e );
110- Logger .warn ("formula: {}" , formula );
111- throw new UncheckedUnParseableFormulaException (s , e );
112- }
113-
114- @ Override
115- public void reportAmbiguity (Parser parser , DFA dfa , int i , int i1 , boolean b , BitSet bitSet , ATNConfigSet atnConfigSet ) {
116- }
11768
118- @ Override
119- public void reportAttemptingFullContext (Parser parser , DFA dfa , int i , int i1 , BitSet bitSet , ATNConfigSet atnConfigSet ) {
120- }
69+ CExpressionParser parser = new CExpressionParser (tokens );
70+ parser .addErrorListener (new ParseErrorListener (formula ));
12171
122- @ Override
123- public void reportContextSensitivity (Parser parser , DFA dfa , int i , int i1 , int i2 , ATNConfigSet atnConfigSet ) {
124- }
125- });
126- ParseTree tree = parser .expression ();
127- return tree .accept (new ControllingCExpressionVisitor ()).toString ();
72+ return parser .expression ().accept (new ControllingCExpressionVisitor ()).toString ();
12873 }
12974}
0 commit comments