Files
Phraseanet/grammar/query.pp
jygaulier 01a83a88a8 PHRAS-3424_recordid-compare-ops_MASTER
add : native pseudo-fields (recordid, database, collection, ...) support comparison operators, e.g. "recordid > 100" ; "database=getty"
2021-04-20 17:58:27 +02:00

201 lines
4.3 KiB
ObjectPascal

%token space \s+
// Symbols
%token parenthese_ \(
%token _parenthese \)
%token bracket_ \[
%token _bracket \]
%token colon :
%token lte <=|
%token gte >=|
%token lt <
%token gt >
%token equal =
// Strings
%token quote_ " -> string
%token string:quoted [^"]+
%token string:_quote " -> default
%token raw_quote_ r" -> raw
%token raw:raw_quoted (?:(?>[^"\\]+)|\\.)+
%token raw:_raw_quote " -> default
// Operators (too bad we can't use preg "i" flag)
%token and [Aa][Nn][Dd]|[Ee][Tt]
%token or [Oo][Rr]|[Oo][Uu]
%token except [Ee][Xx][Cc][Ee][Pp][Tt]|[Ss][Aa][Uu][Ff]
// Rest
%token database database
%token collection collection
%token sha256 sha256
%token geolocation geolocation
%token uuid uuid
%token type type
%token id id|recordid
%token created_on created_(on|at)
%token updated_on updated_(on|at)
%token field_prefix field\.
%token flag_prefix flag\.
%token meta_prefix (?:meta|exif)\.
%token true true|1
%token false false|0
%token word [^\s\(\)\[\]:<>≤≥=]+
// relative order of precedence is NOT > XOR > AND > OR
#query:
::space::? primary()? ::space::?
| catch_all()
catch_all:
( <space>
| <word>
| keyword()
| symbol() #text )*
// Boolean operators
primary:
secondary() ( ::space:: ::except:: ::space:: primary() #except )?
secondary:
ternary() ( ::space:: ::or:: ::space:: primary() #or )?
ternary:
quaternary() ( ::space:: ::and:: ::space:: primary() #and )?
quaternary:
group() #group
| key_value_pair() ( ::space:: primary() #and )?
| term() ( ::space:: key_value_pair() #and )?
// Key value pairs & field level matchers (restricted to a single field)
key_value_pair:
match_key() ::colon:: ::space::? value() #match_expression
| ::flag_prefix:: flag() ::colon:: ::space::? boolean() #flag_statement
| ::field_prefix:: field() ::colon:: ::space::? term() #field_statement
| field() ::colon:: ::space::? term() #field_statement
| key() ::space::? ::lt:: ::space::? value() #less_than
| key() ::space::? ::gt:: ::space::? value() #greater_than
| key() ::space::? ::lte:: ::space::? value() #less_than_or_equal_to
| key() ::space::? ::gte:: ::space::? value() #greater_than_or_equal_to
| key() ::space::? ::equal:: ::space::? value() #equal_to
match_key:
native_key()
| ::meta_prefix:: meta_key()
#native_key:
<database>
| <sha256>
| <uuid>
| <collection>
| <type>
| <id>
key:
geolocation_key()
| native_key()
| timestamp_key()
| ::meta_prefix:: meta_key()
| ::field_prefix:: field_key()
| field_key()
#timestamp_key:
<created_on>
| <updated_on>
#geolocation_key:
<geolocation>
#meta_key:
word_or_keyword()+
#field_key:
word_or_keyword()+
| quoted_string()
#flag:
word_or_keyword()+
#field:
word_or_keyword()+
| quoted_string()
#value:
word_or_keyword()+
| quoted_string()
group:
::space::? ::parenthese_:: ::space::? primary() ::space::? ::_parenthese:: ::space::?
// Thesaurus terms
term:
::bracket_:: text() ::_bracket:: #thesaurus_term
| text() #text
// Free text handling
text:
string()
( <space>? string() )*
( ::space::? context_block() )?
context_block:
::parenthese_:: ::space::? context() ::space::? ::_parenthese:: #context
context:
word_or_keyword() ( <space>? word_or_keyword() )*
// Generic helpers
boolean:
<true>
| <false>
string:
word_or_keyword()+
| quoted_string()
| raw_quoted_string()
word_or_keyword:
<word> | keyword()
quoted_string:
::quote_:: <quoted> ::_quote::
raw_quoted_string:
::raw_quote_:: <raw_quoted> ::_raw_quote::
keyword:
<except>
| <and>
| <or>
| <database>
| <collection>
| <sha256>
| <geolocation>
| <uuid>
| <type>
| <id>
| <created_on>
| <updated_on>
| <field_prefix>
| <flag_prefix>
| <meta_prefix>
| <true>
| <false>
symbol:
<parenthese_>
| <_parenthese>
| <bracket_>
| <_bracket>
| <colon>