Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I create a PEG.js pattern for my DB query (X “AND” Y “AND” …) #592

Closed
gatsbyz opened this issue Nov 27, 2018 · 3 comments
Labels

Comments

@gatsbyz
Copy link

gatsbyz commented Nov 27, 2018

Issue type

QUESTION

Prerequisites

  • Can you reproduce the issue?: YES
  • Did you search the repository issues?: YES
  • Did you check the forums?: YES
  • Did you perform a web search (google, yahoo, etc)?: YES

Description / Example code

So far my parser looks like this.

const parser = peg.generate(`

eq
  = left:attribute "=" right:value { return left == right; }

and
  = left:eq "AND" right:eq { return left && right; }

It is able to read queries like id = 2 AND createdOn = 193242. I want to be able to read id = 2 AND secondId = 444 AND createdOn = 193242 and so on... (Any number of "AND"s). How can I achieve this via PEG.js?

@futagoza
Copy link
Member

This should do it:

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; }

@Mingun
Copy link
Contributor

Mingun commented Nov 27, 2018

Generic solution for any number of operators with any precedence (creates 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 = [*/];
...

@gatsbyz
Copy link
Author

gatsbyz commented Nov 27, 2018

@futagoza sexy brain. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants