Giter VIP home page Giter VIP logo

rql-parser's Introduction

RQL parser

CI Packagist Version Packagist Downloads Packagist License

This is a RQL parsing library written in PHP.

This library consists of the following parts:

  • lexer for tokenization RQL code
  • parser for creating abstract syntax tree

Installation

The preferred way to install library is through composer.

Either run

composer require graviton/rql-parser

or add

"graviton/rql-parser": "*",

to the require section of your composer.json.

Basic usage

<?php
require 'vendor/autoload.php';

// default lexer supports all RQL rules
$lexer = new Graviton\RqlParser\Lexer();

// default parser contains all parsing strategies
$parser = new Graviton\RqlParser\Parser();


// RQL code
$rql = '(eq(a,string:1)|lt(b,2)|(c<>3&d>=string:4&e=eq=boolean:1))&u!=5&not(or(u=6,ge(i,10)))&z=1&(a==2|b<-3|in(c,(2,float:3)))&select(a,b)&sort(+a,-b)&limit(1,2)';

// tokenize RQL
$tokens = $lexer->tokenize($rql);


// parsing
var_dump($parser->parse($tokens));

See also rql-command library. This is a console application to debug RQL lexing and parsing.

Advanced usage

See examples:

Current state

Operators

Basic syntax

  • scalar operators
    • eq(a,b)
    • ne(a,b)
    • lt(a,b)
    • gt(a,b)
    • le(a,b)
    • ge(a,b)
  • array operators
    • in(a,(b,c))
    • out(a,(b,c))
  • logic operators
    • and(eq(a,b),ne(c,d))
    • or(eq(a,b),ne(c,d))
    • not(eq(a,b))

Short logic syntax

  • (eq(a,b)&ne(b,c))
  • (eq(a,b)|ne(b,c))

FIQL syntax

  • scalar operators
    • a=eq=b
    • a=ne=b
    • a=lt=b
    • a=gt=b
    • a=le=b
    • a=ge=b
  • array operators
    • a=in=(b,c)
    • a=out=(b,c)

Simplified FIQL syntax

  • a=b
  • a==b
  • a<>b
  • a!=b
  • a<b
  • a>b
  • a<=b
  • a>=b

Other

  • select(a,b,c)
  • sort(+a,-b)
  • limit(1,2)

All syntax variations may be used together.

Value types

  • string
    • abc
    • abc%20def
  • integer
    • 1, +1, -1
  • float
    • 1., +1., -1.
    • 0.1, +0.1, -0.1,
    • 0.1e5, +0.1e+5, -0.1e-5
    • .1, +.1, -.1
    • .1e5, +.1e+5, -.1e-5
  • boolean
    • true()
    • false()
  • null
    • null()
  • empty
    • empty()
  • date
    • 2015-06-02T20:00:00Z
  • glob
    • abc*
    • ?abc
    • abc*def?

Type casting

  • string:1
  • boolean:0
  • integer:a
  • float:1

Encoding rules

String values

In string values all non-alphanumeric characters must be encoded with a percent (%) sign followed by two hex digits.

Examples:

eq(string,2015%2D05%2D30T15%3A10%3A00Z)
in(string,(%2B1%2E5,%2D1%2E5))
in(string,(null%28%29,empty%28%29,true%28%29,false%28%29))

String encoding in PHP:

function encodeString($value)
{
    return strtr(rawurlencode($value), [
        '-' => '%2D',
        '_' => '%5F',
        '.' => '%2E',
        '~' => '%7E',
    ]);
}

String encoding in JavaScript:

function encodeString(value) {
    return encodeURIComponent(value).replace(/[\-_\.~!\\'\*\(\)]/g, function (char) {
        return '%' + char.charCodeAt(0).toString(16).toUpperCase();
    });
}

Other values

Date, number and const-function values must not be encoded.

Examples:

eq(date,2015-05-30T15:10:00Z)
in(number,(+1.5,-1.5))
in(const,(null(),empty(),true(),false()))

Resources

rql-parser's People

Contributors

dontub avatar lvoogd avatar mrix avatar narcoticfresh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rql-parser's Issues

Spaces in the string value

I get the following error:

Invalid character \" \" at position 14

when executing the following query:

(eq(field,some value with spaces))

I have got around this by amending the REGEX_VALUE const in the Lexer class to:

const REGEX_VALUE = '/(\s|\w|\-|\+|\*|\?|\:|\.|\%[0-9a-f]{2})+/Ai';

Glob in eq() search

I'm seeing unexpected globs in FIQL based eq() searches. I'm testing with rql rql:parser 'name=eq=*'

query
└─ query
   └─ eq
      ├─ name
      └─ //i

I was expecting the following result.

query
└─ query
   └─ eq
      ├─ name
      └─ "*"

Is this a case of me expecting the wrong thing or actually a parser bug?

The same thing also seems to happen with rql rql:parser 'name=*'. I might make sense to expect the following result in this case.

query
└─ query
   └─ like
      ├─ name
      └─ //i

edit: This is not related to FIQL as rql rql:parser 'eq(name,*)' does the same thing...

parenthesis in value is not working.

Hi

When I searched for SKU PAH-BOC-420(2) it throw an exception.
Unexpected token "(" (T_OPEN_PARENTHESIS) (expected T_INTEGER|T_FLOAT|T_STRING|T_DATE) {"userId":243,"exception":"[object] (Graviton\RqlParser\Exception\SyntaxErrorException(code: 0): Unexpected token "(" (T_OPEN_PARENTHESIS) (expected T_INTEGER|T_FLOAT|T_STRING|T_DATE) at /graviton/rql-parser/src/TokenStream.php:86)

above throw exception when I search for like (sku, PAH-BOC-420(2))

Add $tokens to SubLexerInterface::getTokenAt()

In the Lexer class, you should inject the current $tokens when calling $this->subLexer->getTokensAt() so that the SubLexer can perform context-aware decision making.

For example, if you want to use the IdentifierSubLexer from one of your examples but do not want to require string values to be wrapped in quotes, then you could have the IdentifierSubLexer check if the token immediately before it is an operator of some type. If the token is an operator, then an Identifier is not valid in that context and the next SubLexer in the chain should be tried instead.

Lexler error.

v1.0.2
The lexlet throw Exception Invalid scalar token "select" (T_OPERATOR) when I try to decode rgl string containing the name of the node rgl:
Example:
eq(email,select%28a23sd%2Casd%2Casd%29)
eq(email,select(a23sd,asd,asd))
And throw Invalid scalar token "(" (T_OPEN_PARENTHESIS) when I try to decode rgl string with (

Support nested field queries.

Consider an object
{ "id" : 1231321, "amount" : { "total" : 299, "currency" : "USD" } }, how do I query for amount.total=299?

RQL rule changes in 2.*?

Hi..

We are late trying to switch to 2.* in our graviton app, but now i tried that..

I'm a bit confused that also the RQL syntax seem to have changed in that release - the doc changes seemed like only internal/API changes were made.

The first change I encountered is that "." seems not to be a valid character for a field name now.. this breaks our syntax in our app - why was that changed?

Example:
In 1.* this was valid: eq(name.test,Test)
Now in 2.*, this is invalid, as it now states: Invalid character "." at position 7

Can this be added to the 2.* series or will this stay this way?
Currently I don't know if more changes were made..

Thanks

support underscore for properties

I think RQL allow properties with underscores like this

eq(my_property, 5)

The lexer doesn' t parse that.

I modified the src/SubLexer/StringSubLexer.php to make that work and just found out somebody else did the exact same thing:

Datazource@7e0d810

rawurldecode for globs

I think for globs rawurldecode should be used like for strings.
E.g. for like(a,%5C*) the glob should be \*.

If a String start with a number with Like Operator

Hi All,

I have a field with a product name where we are using the like operator to search the product name from MYSQL.

Once it RQL parser creates the token it splits a single string into two tokens.

one with the number and the other with the string part of the input.

For example: if I tried to search with the input name "0234 bedroom set"

The token list will be like that

$token[0] = "0234";
$token[1] = "bedroom set";

image (4)

My expectation should not split the string into Two tokens instead it should create one token with $token[0]="0234 bedroom set".

Doesn't work correct with LONG_INTEGER values

This code:
$rql = 'eq(id,' . time() * 10 . ')';
$lexer = new Lexer();
$parser = Parser::createDefault();
$tokens = $lexer->tokenize($rql);
var_dump($tokens);

will prints bellow:

class Xiag\Rql\Parser\Token#64 (3) {
protected $value =>
string(11) "14641796010"
protected $type =>
int(1)

protected $position =>
int(6)
}

where $type == 1 is Xiag\Rql\Parser\Token::T_INTEGER.

Then Parser will do (int) $value and we'll get PHP_INT_MAX value instead my LONG_INT

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.