grammar Analytics; options { output=AST; language=CSharp; ASTLabelType=CommonTree; backtrack = true; //k=1; } tokens { DEFINE ; RETURN ; AS ; FROM ; WHERE ; HAVING ; GROUP ; GROUPBY ; PAGE ; ORDERBY ; SELECT ; SEMICOLON = ';'; COLON = ':'; COMMA = ','; DOUBLEQUOTE = '"'; UNDERSCORE = '_'; DOT = '.'; PLUS = '+'; MINUS = '-'; NAVSTATERECORDS = 'NavStateRecords'; ALLBASERECORDS = 'AllBaseRecords'; MULTIPLY = '*'; DIVIDE = '/'; LPAREN = '('; RPAREN = ')'; COALESCE = 'COALESCE'; ARB = 'ARB'; AVG = 'AVG'; COUNT = 'COUNT'; COUNTDISTINCT = 'COUNTDISTINCT'; MAX = 'MAX'; MEDIAN = 'MEDIAN'; MIN = 'MIN'; STDDEV = 'STDDEV'; SUM = 'SUM'; VARIANCE = 'VARIANCE'; ABS = 'ABS'; CEIL = 'CEIL'; COS = 'COS'; EXP = 'EXP'; FLOOR = 'FLOOR'; LN = 'LN'; ROUND = 'ROUND'; SIGN = 'SIGN'; SIN = 'SIN'; SQRT = 'SQRT'; TAN = 'TAN'; TO_DURATION = 'TO_DURATION'; TRUNC = 'TRUNC'; F_DIVIDE = 'DIVIDE'; LOG = 'LOG'; F_MINUS = 'MINUS'; MOD = 'MOD'; F_MULTIPLY = 'MULTIPLY'; F_PLUS = 'PLUS'; POWER = 'POWER'; ROUND = 'ROUND'; EXTRACT = 'EXTRACT'; SECOND = 'SECOND'; MINUTE = 'MINUTE'; HOUR = 'HOUR'; DAY_OF_MONTH = 'DAY_OF_MONTH'; DAY_OF_WEEK = 'DAY_OF_WEEK'; DAY_OF_YEAR = 'DAY_OF_YEAR'; DATE = 'DATE'; WEEK = 'WEEK'; MONTH = 'MONTH'; QUARTER = 'QUARTER'; YEAR = 'YEAR'; L_SQ_BRACKET = '['; R_SQ_BRACKET = ']'; IS ; NOT ; NULL ; AND ; OR ; IN ; //EQ = '='; //NOTEQ = '<>'; //LT = '<'; //GT = '>'; //LTE = '<='; //GTE = '>='; } @parser::namespace { Endeca.AnalyticsParser } @lexer::namespace { Endeca.AnalyticsParser } @members { protected void mismatch(IIntStream input, int ttype, BitSet follow) { throw new MismatchedTokenException(ttype, input); } public void RecoverFromMismatchedSet(IIntStream input, RecognitionException e, BitSet follow) { throw e; } } //Alter code generation so catch-clauses get replace with //this action. @rulecatch { catch (RecognitionException e) { throw e; } } query : statements ; statements : statement ( SEMICOLON statement )* ; statement : ( DEFINE | RETURN ) key AS select from? where? groupBy? having? orderBy? page? ; select : SELECT assigns ; assigns : assign (COMMA assigns)* ; assign : expr AS key ; expr : (aggrExpr | unaryFunc LPAREN expr RPAREN | binaryFunc LPAREN expr COMMA expr RPAREN | COALESCE LPAREN expr (COMMA expr)+ RPAREN) ((PLUS | MINUS | MULTIPLY | DIVIDE) expr)* | LPAREN expr RPAREN ; aggrExpr : simpleExpr | aggrFunc LPAREN simpleExpr RPAREN (where)? ; simpleExpr : (key | literal | unaryFunc LPAREN simpleExpr RPAREN | binaryFunc LPAREN simpleExpr COMMA simpleExpr RPAREN | timeDateFunc LPAREN simpleExpr COMMA dateTimeUnit RPAREN | lookupExpr) ( ( PLUS | MINUS | MULTIPLY | DIVIDE ) simpleExpr )* ; aggrFunc : ARB | AVG | COUNT | COUNTDISTINCT | MAX | MEDIAN | MIN | STDDEV | SUM | VARIANCE ; unaryFunc : ABS | CEIL | COS | EXP | FLOOR | LN | ROUND | SIGN | SIN | SQRT | TAN | TO_DURATION | TRUNC ; binaryFunc : F_DIVIDE | LOG | F_MINUS | MOD | F_MULTIPLY | F_PLUS | POWER | ROUND | TRUNC ; timeDateFunc : EXTRACT | TRUNC ; dateTimeUnit : SECOND | MINUTE | HOUR | DAY_OF_MONTH | DAY_OF_WEEK | DAY_OF_YEAR | DATE | WEEK | MONTH | QUARTER | YEAR ; lookupExpr : key L_SQ_BRACKET lookupList R_SQ_BRACKET DOT key ; lookupList : simpleExpr (COMMA lookupList)* ; key : IDENTIFIER ; from : FROM key | FROM NAVSTATERECORDS | FROM ALLBASERECORDS ; where : WHERE^ filter ; groupBy : GROUP | GROUPBY groupings ; groupings : grouping (COMMA groupings)* ; grouping : key | key COLON INTEGER ; having : HAVING^ filter ; orderBy : ORDERBY orderList ; orderList : order (COMMA orderList)* ; order : key ('ASC' | 'DESC') ; page : PAGE LPAREN INTEGER COMMA INTEGER RPAREN ; literal : STRINGLITERAL | numericLiteral ; STRINGLITERAL : '\'' (~'\'')* '\'' ; numericLiteral : (numericLiteralUnsigned | numericLiteralPositive | numericLiteralNegative) ('f' | 'F' | 'd' | 'D')? ; numericLiteralUnsigned : INTEGER | DECIMAL | DOUBLE ; numericLiteralPositive : INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE ; numericLiteralNegative : INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE ; filter : //(key compare literal | key IS NOT? NULL | keyList IN key | NOT filter | LPAREN filter RPAREN) (AND^ filter | OR^ filter)* unaryFilter ((AND | OR) filter)* ; unaryFilter : compareFilter | notNullFilter | keyListFilter | NOT filter | LPAREN filter RPAREN ; compareFilter : key COMPARE compareFilterRightSide -> ^(key COMPARE compareFilterRightSide) ; compareFilterRightSide : literal | PARAMETER ; notNullFilter : key IS NOT? NULL ; keyListFilter : keyList IN key ; keyList : key (COMMA keyList)* ; COMPARE : '=' | '<>' | '<' | '>' | '<=' | '>=' //EQ | NOTEQ | LT | GT | LTE | GTE ; DEFINE : ('D' | 'd') ('E' | 'e') ('F' | 'f') ('I' | 'i') ('N' | 'n') ('E' | 'e') ; RETURN : ('R' | 'r') ('E' | 'e') ('T' | 't') ('U' | 'u') ('R' | 'r') ('N' | 'n') ; AS : ('A' | 'a') ('S' | 's') ; FROM : ('F' | 'f') ('R' | 'r') ('O' | 'o') ('M' | 'm') ; WHERE : ('W' | 'w') ('H' | 'h') ('E' | 'e') ('R' | 'r') ('E' | 'e') ; HAVING : ('H' | 'h') ('A' | 'a') ('V' | 'v') ('I' | 'i') ('N' | 'n') ('G' | 'g') ; GROUP : ('G' | 'g') ('R' | 'r') ('O' | 'o') ('U' | 'u') ('P' | 'p') ; GROUPBY : ('G' | 'g') ('R' | 'r') ('O' | 'o') ('U' | 'u') ('P' | 'p') ' ' ('B' | 'b') ('Y' | 'y') ; PAGE : ('P' | 'p') ('A' | 'a') ('G' | 'g') ('E' | 'e') ; ORDERBY : ('O' | 'o') ('R' | 'r') ('D' | 'd') ('E' | 'e') ('R' | 'r') ' ' ('B' | 'b') ('Y' | 'y') ; SELECT : ('S' | 's') ('E' | 'e') ('L' | 'l') ('E' | 'e') ('C' | 'c') ('T' | 't') ; AND : ('A' | 'a') ('N' | 'n') ('D' | 'd') ; OR : ('O' | 'o') ('R' | 'r') ; IN : ('I' | 'i') ('N' | 'n') ; IS : ('I' | 'i') ('S' | 's') ; NOT : ('N' | 'n') ('O' | 'o') ('T' | 't') ; NULL : ('N' | 'n') ('U' | 'u') ('L' | 'l') ('L' | 'l') ; IDENTIFIER : (UNDERSCORE | LETTER) (UNDERSCORE | LETTER | DIGIT)* | '"' (~'"')* '"' ; PARAMETER : '@' IDENTIFIER ; fragment LETTER : 'a'..'z' | 'A'..'Z' ; fragment DIGIT : '0'..'9' ; INTEGER : (DIGIT)+ ; DECIMAL : DIGIT+ DOT DIGIT* | DOT DIGIT+ ; DOUBLE : DIGIT+ DOT DIGIT* EXPONENT | DOT DIGIT+ EXPONENT | DIGIT+ EXPONENT ; EXPONENT : ('e'|'E') (PLUS|MINUS)? DIGIT+ ; INTEGER_POSITIVE : PLUS INTEGER ; DECIMAL_POSITIVE : PLUS DECIMAL ; DOUBLE_POSITIVE : PLUS DOUBLE ; INTEGER_NEGATIVE : MINUS INTEGER ; DECIMAL_NEGATIVE : MINUS DECIMAL ; DOUBLE_NEGATIVE : MINUS DOUBLE ; WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ {$channel=HIDDEN;} ;