Snippets

Erik van Zijst pRX6q: Untitled snippet

Created by Erik van Zijst
#!/usr/bin/env python
from __future__ import print_function
import traceback

from django.db.models.query_utils import Q
from plyplus import Grammar, STransformer

parser = Grammar("""
  start: _or;

  ?_or: (_or '\|\|')? _and;
  ?_and: (_and '&&')? expr;

  ?expr: (field op value) | '\(' _or '\)';

  field: '\w+';
  op: '=' | '>' | '>=' | '<=' | '<' | '!=';
  value: '"(?:[^"\\\\]|\\\\.)*"';

  WS: '[ \t]+' (%ignore);
""")


class ORMTransformer(STransformer):
    _or = lambda self, exp: Q(exp.tail[0]) | Q(exp.tail[1])
    _and = lambda self, exp: Q(exp.tail[0]) & Q(exp.tail[1])
    expr = lambda self, exp: Q('{}{}={}'.format(*exp.tail))

    field = lambda self, exp: exp.tail[0]
    op = lambda self, exp: {'=': '',
                            '>': '__gt',
                            '>=': '__ge',
                            '<=': '__le',
                            '<': '__lt',
                            '!=': '__ne'}[exp.tail[0]]
    value = lambda self, exp: exp.tail[0][1:-1]

    __default__ = lambda self, exp: exp.tail[0]

print('Interactive BBQL parser.')
print('Type your query below and press enter.')
print('Example:')
print('  foo="b" && f="dsf" && (d!="sadf" || dsaf>="sadf")')


while True:
    try:
        line = raw_input('BBQL> ')
        if not line:
            break

        tree = parser.parse(line)
        print(tree.pretty())
        print(ORMTransformer().transform(tree))
    except EOFError:
        break
    except:
        traceback.print_exc()
$ ./parser.py 
Interactive BBQL parser.
Type your query below and press enter.
Example:
  foo="b" && f="dsf" && (d!="sadf" || dsaf>="sadf")
BBQL> foo="b" && (f="dsf")  && (d!="sadf" || dsaf>="sadf")
start
  _and
    _and
      expr
        field	foo
        op	=
        value	"b"
      expr
        field	f
        op	=
        value	"dsf"
    _or
      expr
        field	d
        op	!=
        value	"sadf"
      expr
        field	dsaf
        op	>=
        value	"sadf"

(AND: (AND: (AND: foo=b), (AND: f=dsf)), (OR: (AND: d__ne=sadf), (AND: dsaf__ge=sadf)))
BBQL> 

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.