1
0
silverbullet/plugs/query/parser.ts

78 lines
2.4 KiB
TypeScript
Raw Normal View History

2022-07-06 10:18:47 +00:00
import {
collectNodesOfType,
findNodeOfType,
replaceNodesMatching,
2022-10-14 13:11:33 +00:00
} from "$sb/lib/tree.ts";
import { lezerToParseTree } from "../../common/parse_tree.ts";
import { valueNodeToVal } from "./engine.ts";
2022-07-06 10:18:47 +00:00
// @ts-ignore auto generated
import { parser } from "./parse-query.js";
2022-10-14 13:11:33 +00:00
import { ParsedQuery, QueryFilter } from "$sb/lib/query.ts";
2022-07-06 10:18:47 +00:00
export function parseQuery(query: string): ParsedQuery {
2022-10-14 13:11:33 +00:00
const n = lezerToParseTree(query, parser.parse(query).topNode);
2022-07-06 10:18:47 +00:00
// Clean the tree a bit
replaceNodesMatching(n, (n) => {
if (!n.type) {
2022-10-14 13:11:33 +00:00
const trimmed = n.text!.trim();
2022-07-06 10:18:47 +00:00
if (!trimmed) {
return null;
}
n.text = trimmed;
}
});
// console.log("Parsed", JSON.stringify(n, null, 2));
2022-10-14 13:11:33 +00:00
const queryNode = n.children![0];
const parsedQuery: ParsedQuery = {
2022-07-06 10:18:47 +00:00
table: queryNode.children![0].children![0].text!,
filter: [],
};
2022-10-14 13:11:33 +00:00
const orderByNode = findNodeOfType(queryNode, "OrderClause");
2022-07-06 10:18:47 +00:00
if (orderByNode) {
2022-10-14 13:11:33 +00:00
const nameNode = findNodeOfType(orderByNode, "Name");
2022-07-06 10:18:47 +00:00
parsedQuery.orderBy = nameNode!.children![0].text!;
2022-10-14 13:11:33 +00:00
const orderNode = findNodeOfType(orderByNode, "Order");
2022-07-06 10:18:47 +00:00
parsedQuery.orderDesc = orderNode
? orderNode.children![0].text! === "desc"
: false;
}
2022-10-14 13:11:33 +00:00
const limitNode = findNodeOfType(queryNode, "LimitClause");
2022-07-06 10:18:47 +00:00
if (limitNode) {
2022-10-14 13:11:33 +00:00
const nameNode = findNodeOfType(limitNode, "Number");
2022-07-06 10:18:47 +00:00
parsedQuery.limit = valueNodeToVal(nameNode!);
}
2022-10-14 13:11:33 +00:00
const filterNodes = collectNodesOfType(queryNode, "FilterExpr");
for (const filterNode of filterNodes) {
2022-07-06 10:18:47 +00:00
let val: any = undefined;
2022-10-14 13:11:33 +00:00
const valNode = filterNode.children![2].children![0];
2022-07-06 10:18:47 +00:00
val = valueNodeToVal(valNode);
2022-10-14 13:11:33 +00:00
const f: QueryFilter = {
2022-07-06 10:18:47 +00:00
prop: filterNode.children![0].children![0].text!,
op: filterNode.children![1].text!,
value: val,
};
parsedQuery.filter.push(f);
}
2022-10-14 13:11:33 +00:00
const selectNode = findNodeOfType(queryNode, "SelectClause");
2022-07-06 10:18:47 +00:00
if (selectNode) {
parsedQuery.select = [];
collectNodesOfType(selectNode, "Name").forEach((t) => {
parsedQuery.select!.push(t.children![0].text!);
});
}
2022-10-14 13:11:33 +00:00
const renderNode = findNodeOfType(queryNode, "RenderClause");
2022-07-06 10:18:47 +00:00
if (renderNode) {
2022-08-09 13:37:47 +00:00
let renderNameNode = findNodeOfType(renderNode, "PageRef");
if (!renderNameNode) {
renderNameNode = findNodeOfType(renderNode, "String");
}
2022-07-06 10:18:47 +00:00
parsedQuery.render = valueNodeToVal(renderNameNode!);
}
return parsedQuery;
}