Write filter grammar & fix priorities

This commit is contained in:
Zoe Roux 2024-12-22 19:25:30 +01:00
parent e20e327286
commit e960307172
No known key found for this signature in database

View File

@ -99,15 +99,24 @@ export const operation = property
) )
.expects("an operation"); .expects("an operation");
const expression = later<Expression>(); // grammar:
//
// operation = property operator value
// property = letter { letter }
// operator = "eq" | "lt" | ...
// value = ...
//
// expression = expr { binn expr }
// expr =
// | "not" expr
// | "(" expression ")"
// | operation
// bin = "and" | "or"
//
const expr = later<Expression>();
const not = t(string("not")).pipe( export const expression = expr.pipe(
qthen(expression), then(t(anyStringOf("and", "or")).pipe(then(expr), many())),
map((expression) => ({ type: "not" as const, expression })),
);
const andor = operation.pipe(
then(anyStringOf("and", "or").pipe(then(expression), many())),
map(([first, expr]) => map(([first, expr]) =>
expr.reduce<Expression>( expr.reduce<Expression>(
(lhs, [op, rhs]) => ({ type: op, lhs, rhs }), (lhs, [op, rhs]) => ({ type: op, lhs, rhs }),
@ -116,11 +125,14 @@ const andor = operation.pipe(
), ),
); );
expression.init( const not = t(string("not")).pipe(
not.pipe(or(operation, expression.pipe(or(andor), between("(", ")")))), qthen(expr),
map((expression) => ({ type: "not" as const, expression })),
); );
export const filterParser = andor.pipe(or(expression)); const brackets = expression.pipe(between("(", ")"));
expr.init(not.pipe(or(brackets, operation)));
export const parseFilter = ( export const parseFilter = (
filter: string, filter: string,