如何为我的数据库查询创建 PEG.js 模式 (X "AND" Y "AND" ...)
How can I create a PEG.js pattern for my DB queries (X "AND" Y "AND" ...)
到目前为止我的解析器看起来像这样。
const parser = peg.generate(`
eq
= left:attribute "=" right:value { return left == right; }
and
= left:eq "AND" right:eq { return left && right; }
它能够读取像 id = 2 AND createdOn = 193242
这样的查询。我希望能够阅读 id = 2 AND secondId = 444 AND createdOn = 193242
等等...(任意数量的 "AND")。如何通过 PEG.js 实现此目的?
应该这样做:
and
= left:eq right:and_eq+ {
if ( right.length === 1 ) return left && right;
// handle more then 1 'AND eq' here
}
and_eq
= "AND" e:eq { return e; }
具有任意优先级的任意数量运算符的通用解决方案(创建 AST):
{
function leftAssotiative(left, tail) {
let r = left;
for (let i = 0; i < tail.length; ++i) {
r = { kind: tail[i][0], left: r, right: tail[i][1] };
}
return r;
}
function rightAssotiative(left, tail) {
if (tail.length > 1) {
let r = tail[tail.length-1][1];
for (let i = tail.length-2; i >= 0; --i) {
r = { kind: tail[i+1][0], left: tail[i][1], right: r };
}
return { kind: tail[0][0], left: left, right: r };
}
return left;
}
}
// Expressions
Expr// minimal priority
= l:Expr0 t:(p0 Expr0)* { return rightAssotiative(l, t); };
Expr0
= l:Expr1 t:(p1 Expr1)* { return leftAssotiative(l, t); };
...
ExprN// maximal priority
= '(' @Expr ')';
// Operators
p0 = [+-];
p1 = [*/];
...
到目前为止我的解析器看起来像这样。
const parser = peg.generate(`
eq
= left:attribute "=" right:value { return left == right; }
and
= left:eq "AND" right:eq { return left && right; }
它能够读取像 id = 2 AND createdOn = 193242
这样的查询。我希望能够阅读 id = 2 AND secondId = 444 AND createdOn = 193242
等等...(任意数量的 "AND")。如何通过 PEG.js 实现此目的?
应该这样做:
and
= left:eq right:and_eq+ {
if ( right.length === 1 ) return left && right;
// handle more then 1 'AND eq' here
}
and_eq
= "AND" e:eq { return e; }
具有任意优先级的任意数量运算符的通用解决方案(创建 AST):
{
function leftAssotiative(left, tail) {
let r = left;
for (let i = 0; i < tail.length; ++i) {
r = { kind: tail[i][0], left: r, right: tail[i][1] };
}
return r;
}
function rightAssotiative(left, tail) {
if (tail.length > 1) {
let r = tail[tail.length-1][1];
for (let i = tail.length-2; i >= 0; --i) {
r = { kind: tail[i+1][0], left: tail[i][1], right: r };
}
return { kind: tail[0][0], left: left, right: r };
}
return left;
}
}
// Expressions
Expr// minimal priority
= l:Expr0 t:(p0 Expr0)* { return rightAssotiative(l, t); };
Expr0
= l:Expr1 t:(p1 Expr1)* { return leftAssotiative(l, t); };
...
ExprN// maximal priority
= '(' @Expr ')';
// Operators
p0 = [+-];
p1 = [*/];
...