import Utils from "./utils" ; import Lexer from "./lexer" ; import PrimitiveLiteral from "./primitiveLiteral" ; import NameOrIdentifier from "./nameOrIdentifier" ; import ArrayOrObject from "./json" ; export namespace Expressions { export function commonExpr ( value , index ) { let token = PrimitiveLiteral . primitiveLiteral ( value , index ) || parameterAlias ( value , index ) || ArrayOrObject . arrayOrObject ( value , index ) || rootExpr ( value , index ) || methodCallExpr ( value , index ) || firstMemberExpr ( value , index ) || functionExpr ( value , index ) || negateExpr ( value , index ) || parenExpr ( value , index ) || castExpr ( value , index ) ; if ( ! token ) return ; let expr = addExpr ( value , token . next ) || subExpr ( value , token . next ) || mulExpr ( value , token . next ) || divExpr ( value , token . next ) || modExpr ( value , token . next ) ; if ( expr ) { token . value = { left : Lexer . clone ( token ) , right : expr . value } ; token . next = expr . value . next ; token . type = expr . type ; token . raw = Utils . stringify ( value , token . position , token . next ) ; } if ( token ) return Lexer . tokenize ( value , token . position , token . next , token , Lexer . TokenType . CommonExpression ) ; } export function boolCommonExpr ( value , index ) { let token = isofExpr ( value , index ) || boolMethodCallExpr ( value , index ) || notExpr ( value , index ) || commonExpr ( value , index ) || boolParenExpr ( value , index ) ; if ( ! token ) return ; let commonMoreExpr = undefined ; if ( token . type === Lexer . TokenType . CommonExpression ) { commonMoreExpr = eqExpr ( value , token . next ) || neExpr ( value , token . next ) || ltExpr ( value , token . next ) || leExpr ( value , token . next ) || gtExpr ( value , token . next ) || geExpr ( value , token . next ) || hasExpr ( value , token . next ) ; if ( commonMoreExpr ) { token . value = { left : token . value , right : commonMoreExpr . value } ; token . next = commonMoreExpr . value . next ; token . type = commonMoreExpr . type ; token . raw = Utils . stringify ( value , token . position , token . next ) ; } } let expr = andExpr ( value , token . next ) || orExpr ( value , token . next ) ; if ( expr ) { let left = Lexer . clone ( token ) ; token . next = expr . value . next ; token . value = { left : left , right : expr . value } ; token . type = expr . type ; token . raw = Utils . stringify ( value , token . position , token . next ) ; if ( token . type === Lexer . TokenType . AndExpression && token . value . right . type === Lexer . TokenType . OrExpression ) { token . value . left = Lexer . tokenize ( value , token . value . left . position , token . value . right . value . left . next , { left : token . value . left , right : token . value . right . value . left } , token . type ) ; token . type = token . value . right . type ; token . value . right = token . value . right . value . right ; } } return token ; } export function andExpr ( value , index ) { let rws = Lexer . RWS ( value , index ) ; if ( rws === index || ! Utils . equals ( value , rws , "and" ) ) return ; let start = index ; index = rws + 3 ; rws = Lexer . RWS ( value , index ) ; if ( rws === index ) return ; index = rws ; let token = boolCommonExpr ( value , index ) ; if ( ! token ) return ; return Lexer . tokenize ( value , start , index , token , Lexer . TokenType . AndExpression ) ; } export function orExpr ( value , index ) { let rws = Lexer . RWS ( value , index ) ; if ( rws === index || ! Utils . equals ( value , rws , "or" ) ) return ; let start = index ; index = rws + 2 ; rws = Lexer . RWS ( value , index ) ; if ( rws === index ) return ; index = rws ; let token = boolCommonExpr ( value , index ) ; if ( ! token ) return ; return Lexer . tokenize ( value , start , index , token , Lexer . TokenType . OrExpression ) ; } export function leftRightExpr ( value , index , expr , tokenType ) { let rws = Lexer . RWS ( value , index ) ; if ( rws === index ) return ; let start = index ; index = rws ; if ( ! Utils . equals ( value , index , expr ) ) return ; index += expr . length ; rws = Lexer . RWS ( value , index ) ; if ( rws === index ) return ; index = rws ; let token = commonExpr ( value , index ) ; if ( ! token ) return ; return Lexer . tokenize ( value , start , index , token . value , tokenType ) ; } export function eqExpr ( value , index ) { return leftRightExpr ( value , index , "eq" , Lexer . TokenType . EqualsExpression ) ; } export function neExpr ( value , index ) { return leftRightExpr ( value , index , "ne" , Lexer . TokenType . NotEqualsExpression ) ; } export function ltExpr ( value , index ) { return leftRightExpr ( value , index , "lt" , Lexer . TokenType . LesserThanExpression ) ; } export function leExpr ( value , index ) { return leftRightExpr ( value , index , "le" , Lexer . TokenType . LesserOrEqualsExpression ) ; } export function gtExpr ( value , index ) { return leftRightExpr ( value , index , "gt" , Lexer . TokenType . GreaterThanExpression ) ; } export function geExpr ( value , index ) { return leftRightExpr ( value , index , "ge" , Lexer . TokenType . GreaterOrEqualsExpression ) ; } export function hasExpr ( value , index ) { return leftRightExpr ( value , index , "has" , Lexer . TokenType . HasExpression ) ; } export function addExpr ( value , index ) { return leftRightExpr ( value , index , "add" , Lexer . TokenType . AddExpression ) ; } export function subExpr ( value , index ) { return leftRightExpr ( value , index , "sub" , Lexer . TokenType . SubExpression ) ; } export function mulExpr ( value , index ) { return leftRightExpr ( value , index , "mul" , Lexer . TokenType . MulExpression ) ; } export function divExpr ( value , index ) { return leftRightExpr ( value , index , "div" , Lexer . TokenType . DivExpression ) ; } export function modExpr ( value , index ) { return leftRightExpr ( value , index , "mod" , Lexer . TokenType . ModExpression ) ; } export function notExpr ( value , index ) { if ( ! Utils . equals ( value , index , "not" ) ) return ; let start = index ; index += 3 ; let rws = Lexer . RWS ( value , index ) ; if ( rws === index ) return ; index = rws ; let token = boolCommonExpr ( value , index ) ; if ( ! token ) return ; return Lexer . tokenize ( value , start , token . next , token , Lexer . TokenType . NotExpression ) ; } export function boolParenExpr ( value , index ) { let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; let start = index ; index = open ; index = Lexer . BWS ( value , index ) ; let token = boolCommonExpr ( value , index ) ; if ( ! token ) return ; index = Lexer . BWS ( value , token . next ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , token , Lexer . TokenType . BoolParenExpression ) ; } export function parenExpr ( value , index ) { let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; let start = index ; index = open ; index = Lexer . BWS ( value , index ) ; let token = commonExpr ( value , index ) ; if ( ! token ) return ; index = Lexer . BWS ( value , token . next ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , token . value , Lexer . TokenType . ParenExpression ) ; } export function boolMethodCallExpr ( value , index ) { return endsWithMethodCallExpr ( value , index ) || startsWithMethodCallExpr ( value , index ) || containsMethodCallExpr ( value , index ) || intersectsMethodCallExpr ( value , index ) ; } export function methodCallExpr ( value , index ) { return indexOfMethodCallExpr ( value , index ) || toLowerMethodCallExpr ( value , index ) || toUpperMethodCallExpr ( value , index ) || trimMethodCallExpr ( value , index ) || substringMethodCallExpr ( value , index ) || substringOfMethodCallExpr ( value , index ) || concatMethodCallExpr ( value , index ) || lengthMethodCallExpr ( value , index ) || yearMethodCallExpr ( value , index ) || monthMethodCallExpr ( value , index ) || dayMethodCallExpr ( value , index ) || hourMethodCallExpr ( value , index ) || minuteMethodCallExpr ( value , index ) || secondMethodCallExpr ( value , index ) || fractionalsecondsMethodCallExpr ( value , index ) || totalsecondsMethodCallExpr ( value , index ) || dateMethodCallExpr ( value , index ) || timeMethodCallExpr ( value , index ) || roundMethodCallExpr ( value , index ) || floorMethodCallExpr ( value , index ) || ceilingMethodCallExpr ( value , index ) || distanceMethodCallExpr ( value , index ) || geoLengthMethodCallExpr ( value , index ) || totalOffsetMinutesMethodCallExpr ( value , index ) || minDateTimeMethodCallExpr ( value , index ) || maxDateTimeMethodCallExpr ( value , index ) || nowMethodCallExpr ( value , index ) ; } export function methodCallExprFactory ( value , index , method , min ? , max ? ) { if ( typeof min === "undefined" ) min = 0 ; if ( typeof max === "undefined" ) max = min ; if ( ! Utils . equals ( value , index , method ) ) return ; let start = index ; index += method . length ; let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; index = open ; index = Lexer . BWS ( value , index ) ; let parameters ; if ( min > 0 ) { parameters = [ ] ; while ( parameters . length < max ) { let expr = commonExpr ( value , index ) ; if ( parameters . length < min && ! expr ) return ; else if ( expr ) { parameters . push ( expr . value ) ; index = expr . next ; index = Lexer . BWS ( value , index ) ; let comma = Lexer . COMMA ( value , index ) ; if ( parameters . length < min && ! comma ) return ; if ( comma ) index = comma ; else break ; index = Lexer . BWS ( value , index ) ; } else break ; } } index = Lexer . BWS ( value , index ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , { method : method , parameters : parameters } , Lexer . TokenType . MethodCallExpression ) ; } export function containsMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "contains" , 2 ) ; } export function startsWithMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "startswith" , 2 ) ; } export function endsWithMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "endswith" , 2 ) ; } export function lengthMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "length" , 1 ) ; } export function indexOfMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "indexof" , 2 ) ; } export function substringMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "substring" , 2 , 3 ) ; } export function substringOfMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "substringof" , 2 ) ; } export function toLowerMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "tolower" , 1 ) ; } export function toUpperMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "toupper" , 1 ) ; } export function trimMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "trim" , 1 ) ; } export function concatMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "concat" , 2 ) ; } export function yearMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "year" , 1 ) ; } export function monthMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "month" , 1 ) ; } export function dayMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "day" , 1 ) ; } export function hourMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "hour" , 1 ) ; } export function minuteMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "minute" , 1 ) ; } export function secondMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "second" , 1 ) ; } export function fractionalsecondsMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "fractionalseconds" , 1 ) ; } export function totalsecondsMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "totalseconds" , 1 ) ; } export function dateMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "date" , 1 ) ; } export function timeMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "time" , 1 ) ; } export function totalOffsetMinutesMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "totaloffsetminutes" , 1 ) ; } export function minDateTimeMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "mindatetime" , 0 ) ; } export function maxDateTimeMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "maxdatetime" , 0 ) ; } export function nowMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "now" , 0 ) ; } export function roundMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "round" , 1 ) ; } export function floorMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "floor" , 1 ) ; } export function ceilingMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "ceiling" , 1 ) ; } export function distanceMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "geo.distance" , 2 ) ; } export function geoLengthMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "geo.length" , 1 ) ; } export function intersectsMethodCallExpr ( value , index ) { return methodCallExprFactory ( value , index , "geo.intersects" , 2 ) ; } export function isofExpr ( value , index ) { if ( ! Utils . equals ( value , index , "isof" ) ) return ; let start = index ; index += 4 ; let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; index = open ; index = Lexer . BWS ( value , index ) ; let expr = commonExpr ( value , index ) ; if ( expr ) { index = expr . next ; index = Lexer . BWS ( value , index ) ; let comma = Lexer . COMMA ( value , index ) ; if ( ! comma ) return ; index = comma ; index = Lexer . BWS ( value , index ) ; } let typeName = NameOrIdentifier . qualifiedTypeName ( value , index ) ; if ( ! typeName ) return ; index = typeName . next ; index = Lexer . BWS ( value , index ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , { target : expr , typename : typeName } , Lexer . TokenType . IsOfExpression ) ; } export function castExpr ( value , index ) { if ( ! Utils . equals ( value , index , "cast" ) ) return ; let start = index ; index += 4 ; let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; index = open ; index = Lexer . BWS ( value , index ) ; let expr = commonExpr ( value , index ) ; if ( expr ) { index = expr . next ; index = Lexer . BWS ( value , index ) ; let comma = Lexer . COMMA ( value , index ) ; if ( ! comma ) return ; index = comma ; index = Lexer . BWS ( value , index ) ; } let typeName = NameOrIdentifier . qualifiedTypeName ( value , index ) ; if ( ! typeName ) return ; index = typeName . next ; index = Lexer . BWS ( value , index ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , { target : expr , typename : typeName } , Lexer . TokenType . CastExpression ) ; } export function negateExpr ( value , index ) { if ( value [ index ] !== 0x2d ) return ; let start = index ; index ++ ; index = Lexer . BWS ( value , index ) ; let expr = commonExpr ( value , index ) ; if ( ! expr ) return ; return Lexer . tokenize ( value , start , expr . next , expr , Lexer . TokenType . NegateExpression ) ; } export function firstMemberExpr ( value , index ) { let token = inscopeVariableExpr ( value , index ) ; let member ; let start = index ; if ( token ) { if ( value [ token . next ] === 0x2f ) { index = token . next + 1 ; member = memberExpr ( value , index ) ; if ( ! member ) return ; return Lexer . tokenize ( value , start , member . next , [ token , member ] , Lexer . TokenType . FirstMemberExpression ) ; } } else member = memberExpr ( value , index ) ; token = token || member ; if ( ! token ) return ; return Lexer . tokenize ( value , start , token . next , token , Lexer . TokenType . FirstMemberExpression ) ; } export function memberExpr ( value , index ) { let start = index ; let token = NameOrIdentifier . qualifiedEntityTypeName ( value , index ) ; if ( token ) { if ( value [ token . next ] !== 0x2f ) return ; index = token . next + 1 ; } let next = propertyPathExpr ( value , index ) || boundFunctionExpr ( value , index ) ; if ( ! next ) return ; return Lexer . tokenize ( value , start , next . next , token ? { name : token , value : next } : next , Lexer . TokenType . MemberExpression ) ; } export function propertyPathExpr ( value , index ) { let token = NameOrIdentifier . odataIdentifier ( value , index ) ; let start = index ; if ( token ) { index = token . next ; let nav = collectionPathExpr ( value , token . next ) || collectionNavigationExpr ( value , token . next ) || singleNavigationExpr ( value , token . next ) || complexPathExpr ( value , token . next ) || singlePathExpr ( value , token . next ) ; if ( nav ) { index = nav . next ; token = { current : Lexer . clone ( token ) , next : nav } ; } } else if ( ! token ) { token = NameOrIdentifier . streamProperty ( value , index ) ; if ( token ) index = token . next ; } if ( ! token ) return ; return Lexer . tokenize ( value , start , index , token , Lexer . TokenType . PropertyPathExpression ) ; } export function inscopeVariableExpr ( value , index ) { return implicitVariableExpr ( value , index ) || ( isLambdaPredicate ? lambdaVariableExpr ( value , index ) : undefined ) ; } export function implicitVariableExpr ( value , index ) { if ( Utils . equals ( value , index , "$it" ) ) return Lexer . tokenize ( value , index , index + 3 , "$it" , Lexer . TokenType . ImplicitVariableExpression ) ; } let isLambdaPredicate = false ; let hasLambdaVariableExpr = false ; export function lambdaVariableExpr ( value , index ) { let token = NameOrIdentifier . odataIdentifier ( value , index , Lexer . TokenType . LambdaVariableExpression ) ; if ( token ) { hasLambdaVariableExpr = true ; return token ; } } export function lambdaPredicateExpr ( value , index ) { isLambdaPredicate = true ; let token = boolCommonExpr ( value , index ) ; isLambdaPredicate = false ; if ( token && hasLambdaVariableExpr ) { hasLambdaVariableExpr = false ; return Lexer . tokenize ( value , token . position , token . next , token , Lexer . TokenType . LambdaPredicateExpression ) ; } } export function anyExpr ( value , index ) { if ( ! Utils . equals ( value , index , "any" ) ) return ; let start = index ; index += 3 ; let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; index = open ; index = Lexer . BWS ( value , index ) ; let variable = lambdaVariableExpr ( value , index ) ; let predicate ; if ( variable ) { index = variable . next ; index = Lexer . BWS ( value , index ) ; let colon = Lexer . COLON ( value , index ) ; if ( ! colon ) return ; index = colon ; index = Lexer . BWS ( value , index ) ; predicate = lambdaPredicateExpr ( value , index ) ; if ( ! predicate ) return ; index = predicate . next ; } index = Lexer . BWS ( value , index ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , { variable : variable , predicate : predicate } , Lexer . TokenType . AnyExpression ) ; } export function allExpr ( value , index ) { if ( ! Utils . equals ( value , index , "all" ) ) return ; let start = index ; index += 3 ; let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; index = open ; index = Lexer . BWS ( value , index ) ; let variable = lambdaVariableExpr ( value , index ) ; if ( ! variable ) return ; index = variable . next ; index = Lexer . BWS ( value , index ) ; let colon = Lexer . COLON ( value , index ) ; if ( ! colon ) return ; index = colon ; index = Lexer . BWS ( value , index ) ; let predicate = lambdaPredicateExpr ( value , index ) ; if ( ! predicate ) return ; index = predicate . next ; index = Lexer . BWS ( value , index ) ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , { variable : variable , predicate : predicate } , Lexer . TokenType . AllExpression ) ; } export function collectionNavigationExpr ( value , index ) { let start = index ; let entity , predicate , navigation , path ; if ( value [ index ] === 0x2f ) { index ++ ; entity = NameOrIdentifier . qualifiedEntityTypeName ( value , index ) ; if ( ! entity ) return ; index = entity . next ; } predicate = keyPredicate ( value , index ) ; if ( predicate ) { index = predicate . next ; navigation = singleNavigationExpr ( value , index ) ; if ( navigation ) index = navigation . next ; } else { path = collectionPathExpr ( value , index ) ; if ( path ) index = path . next ; } if ( index > start ) { return Lexer . tokenize ( value , start , index , { entity : entity , predicate : predicate , navigation : navigation , path : path } , Lexer . TokenType . CollectionNavigationExpression ) ; } } export function keyPredicate ( value , index , metadataContext ? ) { return simpleKey ( value , index , metadataContext ) || compoundKey ( value , index ) ; } export function simpleKey ( value , index , metadataContext ? ) { let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; let start = index ; index = open ; let token = keyPropertyValue ( value , index ) ; if ( ! token ) return ; let close = Lexer . CLOSE ( value , token . next ) ; if ( ! close ) return ; let key ; if ( typeof metadataContext === "object" && metadataContext . key && metadataContext . key . propertyRefs && metadataContext . key . propertyRefs [ 0 ] && metadataContext . key . propertyRefs [ 0 ] . name ) { key = metadataContext . key . propertyRefs [ 0 ] . name ; } return Lexer . tokenize ( value , start , close , { key : key , value : token } , Lexer . TokenType . SimpleKey ) ; } export function compoundKey ( value , index ) { let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; let start = index ; index = open ; let pair = keyValuePair ( value , index ) ; if ( ! pair ) return ; let keys = [ ] ; while ( pair ) { keys . push ( pair ) ; let comma = Lexer . COMMA ( value , pair . next ) ; if ( comma ) pair = keyValuePair ( value , comma ) ; else pair = null ; } index = keys [ keys . length - 1 ] . next ; let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , keys , Lexer . TokenType . CompoundKey ) ; } export function keyValuePair ( value , index ) { let prop = NameOrIdentifier . primitiveKeyProperty ( value , index ) || keyPropertyAlias ( value , index ) ; if ( ! prop ) return ; let eq = Lexer . EQ ( value , prop . next ) ; if ( ! eq ) return ; let val = keyPropertyValue ( value , eq ) ; if ( val ) return Lexer . tokenize ( value , index , val . next , { key : prop , value : val } , Lexer . TokenType . KeyValuePair ) ; } export function keyPropertyValue ( value , index ) { let token = PrimitiveLiteral . primitiveLiteral ( value , index ) ; if ( token ) { token . type = Lexer . TokenType . KeyPropertyValue ; return token ; } } export function keyPropertyAlias ( value , index ) { return NameOrIdentifier . odataIdentifier ( value , index , Lexer . TokenType . KeyPropertyAlias ) ; } export function singleNavigationExpr ( value , index ) { if ( value [ index ] !== 0x2f ) return ; let member = memberExpr ( value , index + 1 ) ; if ( member ) return Lexer . tokenize ( value , index , member . next , member , Lexer . TokenType . SingleNavigationExpression ) ; } export function collectionPathExpr ( value , index ) { let token = countExpr ( value , index ) ; if ( ! token ) { if ( value [ index ] === 0x2f ) { token = boundFunctionExpr ( value , index + 1 ) || anyExpr ( value , index + 1 ) || allExpr ( value , index + 1 ) ; } } if ( token ) return Lexer . tokenize ( value , index , token . next , token , Lexer . TokenType . CollectionPathExpression ) ; } export function complexPathExpr ( value , index ) { if ( value [ index ] !== 0x2f ) return ; let start = index ; index ++ ; let token = NameOrIdentifier . qualifiedComplexTypeName ( value , index ) ; if ( token ) { if ( value [ token . next ] !== 0x2f ) return ; index = token . next + 1 ; } let expr = propertyPathExpr ( value , index ) || boundFunctionExpr ( value , index ) ; if ( expr ) return Lexer . tokenize ( value , start , expr . next , token ? [ token , expr ] : [ expr ] , Lexer . TokenType . ComplexPathExpression ) ; } export function singlePathExpr ( value , index ) { if ( value [ index ] !== 0x2f ) return ; let boundFunction = boundFunctionExpr ( value , index + 1 ) ; if ( boundFunction ) return Lexer . tokenize ( value , index , boundFunction . next , boundFunction , Lexer . TokenType . SinglePathExpression ) ; } export function functionExpr ( value , index ) { let namespaceNext = NameOrIdentifier . namespace ( value , index ) ; if ( namespaceNext === index || value [ namespaceNext ] !== 0x2e ) return ; let start = index ; index = namespaceNext + 1 ; let token = NameOrIdentifier . odataIdentifier ( value , index ) ; if ( ! token ) return ; token . position = start ; token . value . namespace = Utils . stringify ( value , start , namespaceNext ) ; token . raw = Utils . stringify ( value , start , token . next ) ; index = token . next ; let params = functionExprParameters ( value , index ) ; if ( ! params ) return ; index = params . next ; let expr = collectionPathExpr ( value , index ) || collectionNavigationExpr ( value , index ) || singleNavigationExpr ( value , index ) || complexPathExpr ( value , index ) || singlePathExpr ( value , index ) ; if ( expr ) index = expr . next ; return Lexer . tokenize ( value , start , index , { fn : token , params : params , expression : expr } , Lexer . TokenType . FunctionExpression ) ; } export function boundFunctionExpr ( value , index ) { return functionExpr ( value , index ) ; } export function functionExprParameters ( value , index ) { let open = Lexer . OPEN ( value , index ) ; if ( ! open ) return ; let start = index ; index = open ; let params = [ ] ; let expr = functionExprParameter ( value , index ) ; while ( expr ) { params . push ( expr ) ; let comma = Lexer . COMMA ( value , expr . next ) ; if ( comma ) { index = comma ; expr = functionExprParameter ( value , index ) ; if ( ! expr ) return ; } else { index = expr . next ; expr = null ; } } let close = Lexer . CLOSE ( value , index ) ; if ( ! close ) return ; index = close ; return Lexer . tokenize ( value , start , index , params , Lexer . TokenType . FunctionExpressionParameters ) ; } export function functionExprParameter ( value , index ) { let name = parameterName ( value , index ) ; if ( ! name ) return ; let eq = Lexer . EQ ( value , name . next ) ; if ( ! name || ! eq ) return ; let start = index ; index = eq ; let param = parameterAlias ( value , index ) || parameterValue ( value , index ) ; if ( ! param ) return ; return Lexer . tokenize ( value , start , param . next , { name : name , value : param } , Lexer . TokenType . FunctionExpressionParameter ) ; } export function parameterName ( value , index ) { return NameOrIdentifier . odataIdentifier ( value , index , Lexer . TokenType . ParameterName ) ; } export function parameterAlias ( value , index ) { let at = Lexer . AT ( value , index ) ; if ( ! at ) return ; let id = NameOrIdentifier . odataIdentifier ( value , at ) ; if ( id ) return Lexer . tokenize ( value , index , id . next , id . value , Lexer . TokenType . ParameterAlias ) ; } export function parameterValue ( value , index ) { let token = ArrayOrObject . arrayOrObject ( value , index ) || commonExpr ( value , index ) ; if ( token ) return Lexer . tokenize ( value , index , token . next , token . value , Lexer . TokenType . ParameterValue ) ; } export function countExpr ( value , index ) { if ( Utils . equals ( value , index , "/$count" ) ) return Lexer . tokenize ( value , index , index + 7 , "/$count" , Lexer . TokenType . CountExpression ) ; } export function refExpr ( value , index ) { if ( Utils . equals ( value , index , "/$ref" ) ) return Lexer . tokenize ( value , index , index + 5 , "/$ref" , Lexer . TokenType . RefExpression ) ; } export function valueExpr ( value , index ) { if ( Utils . equals ( value , index , "/$value" ) ) return Lexer . tokenize ( value , index , index + 7 , "/$value" , Lexer . TokenType . ValueExpression ) ; } export function rootExpr ( value , index ) { if ( ! Utils . equals ( value , index , "$root/" ) ) return ; let start = index ; index += 6 ; let entitySet = NameOrIdentifier . entitySetName ( value , index ) ; let predicate , entity , token ; if ( entitySet ) predicate = keyPredicate ( value , entitySet . next ) ; if ( ! ( entitySet && predicate ) ) { entity = NameOrIdentifier . singletonEntity ( value , index ) ; if ( ! entity ) return ; token = { entity : entity } ; } else token = { entitySet : entitySet , keys : predicate } ; index = ( predicate || entity ) . next ; let nav = singleNavigationExpr ( value , index ) ; if ( nav ) index = nav . next ; return Lexer . tokenize ( value , start , index , { current : token , next : nav } , Lexer . TokenType . RootExpression ) ; } } export default Expressions ;