I am working through the process of building a regex to match all valid @filter(... )
Has anyone done this already to save some time?
I am working through the process of building a regex to match all valid @filter(... )
Has anyone done this already to save some time?
Well, my language of choice at the moment (Javascript) does not support recursive regex matching very well. So, I will probably just cheat my code for now and match anything in the @filter
string as hopefully being valid. I will have to catch errors later on in the process.
(\s@filter\(.+\))?$
Well, if you do it, Do post it here.
would help people like me save some time
Here is where I ended up at if anyone want to pick it up from here…
https://www.regexpal.com/?fam=118254
^\s*@filter\((?:(?:eq|ge|gt|le|lt)\((?:(?:[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?|val\([a-zA-Z0-9_]+\)|count\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?\)),\s*(?:"[^"]*"|true|false|[0-9]+|val\([a-zA-Z0-9_]+\)|\[(?:"[^"]*"|[0-9]+|val\([a-zA-Z0-9_]+\))(?:,\s*(?:"[^"]*"|[0-9]+|val\([a-zA-Z0-9_]+\)))?\]))\)|(?:allofterms|anyofterms|alloftext|anyoftext)\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?,\s*"[^"]*"\)|regexp\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?,\s*\/[^\/]+\/i?\)|has\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?\)|uid\((?:0x[0-9a-f]+(?:,\s*0x[0-9a-f]+)*|[a-zA-Z0-9]+(?:,\s*[a-zA-Z0-9]+)*)\)|uid_in\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?,\s*0x[0-9a-f]+\)|match\([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)?,\s*"[^"]*",\s*[1-9][0-9]*\))\)$
Which will successfully match the following:
@filter(has(foo))
@filter(uid(0x1))
@filter(uid(0x2a,0x4f))
@filter(uid(foo))
@filter(uid(foo,bar))
@filter(uid_in(foo,0x3af))
@filter(match(foo,"bar",3))
@filter(match(foo, "baz", 8))
@filter(regexp(foo,/bar/))
@filter(regexp(foo,/bar/i))
@filter(allofterms(foo,"bar"))
@filter(anyofterms(foo,"bar"))
@filter(alloftext(foo,"bar"))
@filter(alloftext(foo,"bar"))
@filter(eq(foo,"bar"))
@filter(gt(foo.bar, true))
@filter(ge(foo, 1))
@filter(lt(foo, val(bar)))
@filter(le(val(foo), "bar"))
@filter(ge(count(foo), 1))
@filter(eq(foo.bar, ["baz"]))
@filter(eq(foo.bar, [1]))
@filter(eq(foo.bar, [val(baz)]))
@filter(eq(foo.bar, ["baz", "quz"]))
And will not match these because they are invalid:
@filter(has(foo.bar.baz))
@filter(uid(val(foo)))
@filter(uid_in(foo,0xz))
@filter(match(foo,"bar",0))
@filter(match(foo, baz, 8))
@filter(regexp(foo,/bar))
@filter(regexp(foo,/bar/g))
@filter(allofterms(foo,bar"))
@filter(anyofterms(foo,"bar))
@filter(alloftext(foo,bar))
@filter(someoftext(foo,"bar"))
@filter(eq(foo,bar))
@filter(gt(foo.bar, null))
@filter(gte(foo, 1))
@filter(lt(foo, val(bar.baz)))
@filter(eq(foo.bar, [true]))
But it should match these combined filters but doesn’t:
@filter(NOT has(foo))
@filter(has(foo) AND has(bar))
@filter(has(foo) OR has(bar))
@filter((has(foo) OR has(bar)))
@filter(NOT (has(foo) OR has(bar)))
@filter(has(foo) OR NOT has(bar))
@filter(NOT has(foo) OR NOT has(bar))
@filter(has(foo) OR (has(bar) AND has(baz)))
@filter(has(foo) OR (has(bar) AND NOT has(baz)))
@filter(has(foo) OR (has(bar) AND (has(baz) OR has(quz))))
I would have given up, midway.
Excerpt from Coding Horror:
Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.
– Jamie Zawinski
So I embarked on a quest to find a Machine Learning / Genetic Algorithm based website which would do the job for me.
I found one: Regex Generator & it’s online demo: Regex Golf
I used @amaster507’s sample data to train the model.
Alas, after 1 hour 32 minutes, it failed miserably!
How about using eval to evaluate the filters?!?
Advantages:
const foo = true;
const bar = true;
const baz = true;
function validate(f) {
f = f.replace(/@/, '').replace(/OR/ig, '||').replace(/AND/ig, '&&').replace(/NOT/ig, '!');
try {
console.log(`${eval(f) ? 'Valid' : 'Invalid'}: ${f}`);
} catch (e) {
console.log(`Invalid: ${f}`);
}
}
function filter(x) {
return x != null;
}
function has(v) {
return v;
}
function val(x) {
return x;
}
function count(x) {
return x;
}
function uid(x, y) {
return x;
}
function uid_in(x, y) {
return x;
}
function match(x, y, z) {
return x;
}
function regexp(x, y) {
return x;
}
function allofterms(x, y) {
return (x && typeof y === "string");
}
function anyofterms(x, y) {
return (x && typeof y === "string");
}
function alloftext(x, y) {
return (x && typeof y === "string");
}
function eq(x, y) {
return y;
}
function gt(x, y) {
return y;
}
function ge(x, y) {
return y;
}
function lt(x, y) {
return y;
}
function le(x, y) {
return y;
}
P.S. Not finishing the above approach, in case the solution is not optimal.