From 1003d283ee1b2710d5fac4cd5ff1f2f0e99e6e62 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:32:45 +0000 Subject: [PATCH] Add support for simple compare expression to preprocessor (#7133) Co-authored-by: Martin Valigursky --- src/core/preprocessor.js | 31 ++++++++++++++++++++++-- test/core/preprocessor.test.mjs | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/core/preprocessor.js b/src/core/preprocessor.js index 3f5f271e64e..bd8871a36fc 100644 --- a/src/core/preprocessor.js +++ b/src/core/preprocessor.js @@ -30,8 +30,11 @@ const IDENTIFIER = /([\w-]+)/; // [!]defined(EXPRESSION) const DEFINED = /(!|\s)?defined\(([\w-]+)\)/; +// Matches comparison operators like ==, !=, <, <=, >, >= +const COMPARISON = /([a-z_]\w*)\s*(==|!=|<|<=|>|>=)\s*([\w"']+)/i; + // currently unsupported characters in the expression: | & < > = + - -const INVALID = /[><=|&+-]/g; +const INVALID = /[|&+-]/g; // #include "identifier" const INCLUDE = /include[ \t]+"([\w-]+)"\r?(?:\n|$)/g; @@ -374,6 +377,7 @@ class Preprocessor { * - expression * - defined(expression) * - !defined(expression) + * - simple comparisons like "XX == 3" or "XX != test" * * But does not handle more complex cases, which would require more complex system: * @@ -388,7 +392,7 @@ class Preprocessor { const correct = INVALID.exec(expression) === null; Debug.assert(correct, `Resolving expression like this is not supported: ${expression}`); - // if the format is defined(expression), extract expression + // if the format is 'defined(expression)', extract expression let invert = false; const defined = DEFINED.exec(expression); if (defined) { @@ -396,6 +400,29 @@ class Preprocessor { expression = defined[2]; } + // if the expression is a comparison, evaluate it + const comparison = COMPARISON.exec(expression); + if (comparison) { + const left = defines.get(comparison[1]) ?? comparison[1]; + const right = defines.get(comparison[3]) ?? comparison[3]; + const operator = comparison[2]; + + let result = false; + switch (operator) { + case '==': result = left === right; break; + case '!=': result = left !== right; break; + case '<': result = left < right; break; + case '<=': result = left <= right; break; + case '>': result = left > right; break; + case '>=': result = left >= right; break; + } + + return { + result, + error: !correct + }; + } + // test if expression define exists expression = expression.trim(); let exists = defines.has(expression); diff --git a/test/core/preprocessor.test.mjs b/test/core/preprocessor.test.mjs index 79503ca4b23..d722980cc1c 100644 --- a/test/core/preprocessor.test.mjs +++ b/test/core/preprocessor.test.mjs @@ -73,6 +73,28 @@ describe('Preprocessor', function () { #ifdef (UNKNOWN) #define TEST14 // this should not be defined #endif + + #define INDEX 3 + #if INDEX == 3 + CMP1 + #endif + + #if INDEX != 3 + CMP2 + #endif + + #if INDEX > 2 + CMP3 + #endif + + #define NAME hello + #if NAME == hello + CMP4 + #endif + + #if NAME != hello + CMP5 + #endif `; it('returns false for MORPH_A', function () { @@ -154,4 +176,25 @@ describe('Preprocessor', function () { it('returns true for nested', function () { expect(Preprocessor.run(srcData, includes).includes('nested')).to.equal(true); }); + + it('returns true for CMP1', function () { + expect(Preprocessor.run(srcData, includes).includes('CMP1')).to.equal(true); + }); + + it('returns false for CMP2', function () { + expect(Preprocessor.run(srcData, includes).includes('CMP2')).to.equal(false); + }); + + it('returns true for CMP3', function () { + expect(Preprocessor.run(srcData, includes).includes('CMP3')).to.equal(true); + }); + + it('returns true for CMP4', function () { + expect(Preprocessor.run(srcData, includes).includes('CMP4')).to.equal(true); + }); + + it('returns false for CMP5', function () { + expect(Preprocessor.run(srcData, includes).includes('CMP5')).to.equal(false); + }); + });