feat(wpcarro/slx): Support numeric comparisons

I was (and still ~am) a bit leery of supporting this (scope creep?), but I need
it in two of my personal projects all within the first O(days) of using this. So
I'm thinking that if this tool is going to be a workhorse, I'll need to
sacrifice some purity for practicality. Future me will find out the real
answer...

Change-Id: Ia71a8cf6627062440476b638d2c194c2c9ac97c4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7878
Autosubmit: wpcarro <wpcarro@gmail.com>
Reviewed-by: wpcarro <wpcarro@gmail.com>
Tested-by: BuildkiteCI
This commit is contained in:
William Carroll 2023-01-20 08:04:22 -08:00 committed by clbot
parent 259faea2b2
commit 9df188ad03

View file

@ -49,6 +49,19 @@ function compile(ast, config) {
}; };
} }
} }
if (ast.type === 'COMPARE_SELECTION') {
const f = compile(ast.val, config);
let compare = null;
if (ast.operator === 'LT') { compare = (x, y) => x < y; }
if (ast.operator === 'GT') { compare = (x, y) => x > y; }
if (ast.operator === 'LTE') { compare = (x, y) => x <= y; }
if (ast.operator === 'GTE') { compare = (x, y) => x >= y; }
return function(row) {
return ast.negate ? !compare(row[ast.key], ast.val) : compare(row[ast.key], ast.val);
};
}
if (ast.type === 'SELECTION') { if (ast.type === 'SELECTION') {
const f = compile(ast.val, config); const f = compile(ast.val, config);
return function(row) { return function(row) {
@ -116,6 +129,17 @@ function tokenize(x) {
i += 1; i += 1;
continue; continue;
} }
// Tokenize numbers (i.e. integers, floats).
if (/[0-9]/.test(x[i])) {
let curr = x[i];
i += 1;
while (i < x.length && /[0-9]/.test(x[i])) {
curr += x[i];
i += 1;
}
result.push(['NUMBER', parseFloat(curr)]);
continue;
}
if (ATOM_REGEX.test(x[i])) { if (ATOM_REGEX.test(x[i])) {
let curr = x[i]; let curr = x[i];
i += 1; i += 1;
@ -126,6 +150,26 @@ function tokenize(x) {
result.push(['ATOM', curr]); result.push(['ATOM', curr]);
continue; continue;
} }
if (x[i] === '<' && i + 1 < x.length && x[i + 1] === '=') {
result.push(['COMPARE', 'LTE']);
i += 1;
continue;
}
if (x[i] === '<') {
result.push(['COMPARE', 'LT']);
i += 1;
continue;
}
if (x[i] === '>' && i + i < x.length && x[i + 1] === '=') {
result.push(['COMPARE', 'GTE']);
i += 1;
continue;
}
if (x[i] === '>') {
result.push(['COMPARE', 'GT']);
i += 1;
continue;
}
if (x[i] === ':') { if (x[i] === ':') {
result.push(['COLON', null]); result.push(['COLON', null]);
i += 1; i += 1;
@ -297,7 +341,29 @@ function selection(p, config) {
val, val,
}; };
} }
} else { }
// column<value OR -column<value
else if ((peekType(0, p) === 'ATOM' && peekType(1, p) === 'COMPARE') ||
(peekType(0, p) === 'NEGATE' && peekType(1, p) === 'ATOM' && peekType(2, p) === 'COMPARE')) {
let negate = false;
if (p.tokens[p.i][0] === 'NEGATE') {
negate = true;
p.i += 1;
}
const key = match((type, _) => type === 'ATOM', 'a column label', p);
const operator = match((type, _) => type === 'COMPARE', 'a comparison operator (i.e. "<", ">", "<=", ">=")', p);
const val = match((type, _) => type === 'NUMBER', 'a number', p);
return {
type: 'COMPARE_SELECTION',
operator,
negate,
key,
val,
};
}
else {
return matchAll(p, config); return matchAll(p, config);
} }
} }