Skip to content

Commit

Permalink
Add support for simple compare expression to preprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Valigursky committed Nov 22, 2024
1 parent a4b9c1c commit 1ce08cb
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
31 changes: 29 additions & 2 deletions src/core/preprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
*
Expand All @@ -388,14 +392,37 @@ 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) {
invert = defined[1] === '!';
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);
Expand Down
43 changes: 43 additions & 0 deletions test/core/preprocessor.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down Expand Up @@ -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);
});

});

0 comments on commit 1ce08cb

Please sign in to comment.