@1771technologies/lytenyte-pro
Version:
Blazingly fast headless React data grid with 100s of features.
104 lines (103 loc) • 3.49 kB
JavaScript
import { current, advance } from "../parser/parser-context.js";
import { parseExpression } from "../parser/parse-expression.js";
const LOGICAL_PRECEDENCE = {
"||": 10,
"&&": 20,
"??": 25,
};
export const logicalPlugin = {
name: "logical",
infixPrecedence: (ctx) => {
const tok = current(ctx);
if (tok.type === "Operator" && (tok.value === "&&" || tok.value === "||")) {
return LOGICAL_PRECEDENCE[tok.value];
}
if (tok.type === "NullishCoalescing") {
return LOGICAL_PRECEDENCE["??"];
}
return undefined;
},
parseInfix: (ctx, left, minPrec) => {
const tok = current(ctx);
let op;
let prec;
if (tok.type === "Operator" && (tok.value === "&&" || tok.value === "||")) {
op = tok.value;
prec = LOGICAL_PRECEDENCE[op];
}
else if (tok.type === "NullishCoalescing") {
op = "??";
prec = LOGICAL_PRECEDENCE["??"];
}
if (op === undefined || prec === undefined || prec < minPrec)
return null;
advance(ctx);
const right = parseExpression(ctx, prec + 1);
return {
type: "BinaryExpression",
operator: op,
left,
right,
start: left.start,
end: right.end,
};
},
parseUnary: (ctx, parseNext) => {
const tok = current(ctx);
if (tok.type === "Operator" && tok.value === "!") {
advance(ctx);
const operand = parseNext(ctx);
return {
type: "UnaryExpression",
operator: "!",
operand,
start: tok.start,
end: operand.end,
};
}
return null;
},
optimize: (node, opt) => {
if (node.type === "UnaryExpression" && node.operator === "!") {
const operand = opt(node.operand);
if (operand.type === "BooleanLiteral") {
return {
type: "BooleanLiteral",
value: !operand.value,
start: node.start,
end: node.end,
};
}
return { ...node, operand };
}
if (node.type === "BinaryExpression" &&
(node.operator === "&&" || node.operator === "||" || node.operator === "??")) {
const left = opt(node.left);
const right = opt(node.right);
return { ...node, left, right };
}
return null;
},
evaluate: (node, context, evalFn) => {
if (node.type === "UnaryExpression" && node.operator === "!") {
const operand = evalFn(node.operand, context);
return { value: !operand };
}
if (node.type === "BinaryExpression") {
const op = node.operator;
if (op === "&&") {
const left = evalFn(node.left, context);
return { value: left ? evalFn(node.right, context) : left };
}
if (op === "||") {
const left = evalFn(node.left, context);
return { value: left ? left : evalFn(node.right, context) };
}
if (op === "??") {
const left = evalFn(node.left, context);
return { value: left != null ? left : evalFn(node.right, context) };
}
}
return null;
},
};