<commit_before>grammar QueryFilter;

options {
    output=AST;
    ASTLabelType=CommonTree;
}

@header {
package org.usergrid.persistence.query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usergrid.persistence.Query;
import org.usergrid.persistence.Query.FilterPredicate;
import org.usergrid.persistence.Query.SortPredicate;

}

@lexer::header {
package org.usergrid.persistence.query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

}

@members {
	Query query = new Query();

  private static final Logger logger = LoggerFactory
      .getLogger(QueryFilterLexer.class);

	@Override
	public void emitErrorMessage(String msg) {
		logger.info(msg);
	}
}
  
@lexer::members {

  private static final Logger logger = LoggerFactory
      .getLogger(QueryFilterLexer.class);

	@Override
	public void emitErrorMessage(String msg) {
		logger.info(msg);
	}
}

ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'.')*
    ;

INT :	('-')? '0'..'9'+
    ;

FLOAT
    :  ('-')? ( ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT)
    ;
    
STRING
    :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''
    ;
    
fragment
BOOLEAN :	('true' |'false');
    
UUID :	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

WS : (' ' | '\t' | '\n' | '\r' | '\f')+  {$channel=HIDDEN;};

LT 	:	'<' | 'lt';

LTE	:	'<=' |  'lte';

EQ  : '=' | 'eq';

GT 	:	'>' | 'gt';

GTE	:	'>=' |  'gte';	

NE : '!=';



property 
	:	 ID;
	
value   : BOOLEAN | STRING | INT | FLOAT | UUID;
	
//mathmatical equality operations
equalityop :	
  property ( LT 
	| LTE 
	| EQ
	| GT 
	| GTE
	| NE ) value;

//geo location search
locationop:

  property 'within' FLOAT 'of' FLOAT ',' FLOAT {
  //TODO construct within op object
  };
  
//string search
containsop : 
  property 'contains' STRING ;
  
//
operation :
 equalityop | locationop | containsop;

//negations of operations
notexp :
 'not'^ operation|operation;
    

//and expressions contain operands.  These should always be closer to the leaves of a tree, it allows
//for faster result intersection sooner in the query execution
andexp :
 notexp ('and' notexp)*;
 
//or expression should always be after AND expressions.  This will give us a smaller result set to union when evaluating trees
orexp :
 andexp ('or' andexp)*;

//root level boolean expression
expression:
 orexp;
// | '('expression')';


direction  : ('asc' | 'desc');

order
  : (property direction?);

ql returns [Query q]
  : ('where' expression )? ('order by' order (',' order)*)? {

q = query;

};

//
//
//second_value 	:	(BOOLEAN | STRING | INT | FLOAT | UUID);
//
//third_value 	:	(BOOLEAN | STRING | INT | FLOAT | UUID);
//
//filter returns [FilterPredicate filter] 
//    :   property operator value ((',' | 'of') second_value ( ',' third_value)?)?  {
//    
//String property = $property.text;
//String operator = $operator.text;<commit_msg>Before rewrite rules<commit_after>grammar QueryFilter;

options {
    output=AST;
    ASTLabelType=CommonTree;
}

@header {
package org.usergrid.persistence.query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usergrid.persistence.Query;
import org.usergrid.persistence.Query.FilterPredicate;
import org.usergrid.persistence.Query.SortPredicate;

}

@lexer::header {
package org.usergrid.persistence.query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

}

@members {
	Query query = new Query();

  private static final Logger logger = LoggerFactory
      .getLogger(QueryFilterLexer.class);

	@Override
	public void emitErrorMessage(String msg) {
		logger.info(msg);
	}
}
  
@lexer::members {

  private static final Logger logger = LoggerFactory
      .getLogger(QueryFilterLexer.class);

	@Override
	public void emitErrorMessage(String msg) {
		logger.info(msg);
	}
}

ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'.')*
    ;

INT :	('-')? '0'..'9'+
    ;

FLOAT
    :  ('-')? ( ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT)
    ;
    
STRING
    :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''
    ;
    
fragment
BOOLEAN :	('true' |'false');
    
UUID :	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT '-' 
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
	;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

WS : (' ' | '\t' | '\n' | '\r' | '\f')+  {$channel=HIDDEN;};

LT 	:	'<' | 'lt';

LTE	:	'<=' |  'lte';

EQ  : '=' | 'eq';

GT 	:	'>' | 'gt';

GTE	:	'>=' |  'gte';	

NE : '!=';



property 
	:	 ID;
	
value   : BOOLEAN | STRING | INT | FLOAT | UUID;
	
//mathmatical equality operations
equalityop :	
  property ( LT 
	| LTE 
	| EQ
	| GT 
	| GTE
	| NE ) value;

//geo location search
locationop:

  property 'within' FLOAT 'of' FLOAT ',' FLOAT {
  //TODO construct within op object
  };
  
//string search
containsop : 
  property 'contains' STRING ;
  
//
operation :
 '('! expression ')'! | equalityop | locationop | containsop;

//negations of operations
notexp :
 'not'^ operation|operation;
    

//and expressions contain operands.  These should always be closer to the leaves of a tree, it allows
//for faster result intersection sooner in the query execution
andexp :
 notexp ('and' notexp)*;
 
//or expression should always be after AND expressions.  This will give us a smaller result set to union when evaluating trees
orexp :
 andexp ('or' andexp)*;

//root level boolean expression
expression:
  orexp;

//direction for ordering
direction  : ('asc' | 'desc');

//order cause
order
  : (property direction?);

ql returns [Query q]
  : ('where' expression )? ('order by' order (',' order)*)? {

q = query;

//TODO other stuff
};

//
//
//second_value 	:	(BOOLEAN | STRING | INT | FLOAT | UUID);
//
//third_value 	:	(BOOLEAN | STRING | INT | FLOAT | UUID);
//
//filter returns [FilterPredicate filter] 
//    :   property operator value ((',' | 'of') second_value ( ',' third_value)?)?  {
//    
//String property = $property.text;
//String operator = $operator.text;
{'fraction_non_alphanumeric': 0.19018571234919343, 'fraction_numerical': 0.008675613392978175, 'mean_word_length': 3.1217877094972066, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1465188', 'n_tokens_mistral': 3175, 'n_tokens_neox': 3052, 'n_words': 633}