// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. // -------------------------------------------------------------------------------- // // JavaCC options. When this file is changed, run "ant compileparser" to rebuild // the parser classes. // // -------------------------------------------------------------------------------- options { CACHE_TOKENS = true; STATIC = false; DEBUG_PARSER = false; USER_TOKEN_MANAGER = false; USER_CHAR_STREAM = true; ERROR_REPORTING = true; } // -------------------------------------------------------------------------------- // // Parser body. // // -------------------------------------------------------------------------------- PARSER_BEGIN(GroupingParser) package com.yahoo.search.grouping.request.parser; import java.util.List; import java.util.LinkedList; import com.yahoo.javacc.UnicodeUtilities; import com.yahoo.search.grouping.request.*; @SuppressWarnings({ "ConstantIfStatement", "UnnecessarySemicolon", "Convert2Diamond", "FinalPrivateMethod" }) public class GroupingParser { private static Number resolveNumber(String str) { if (str.indexOf('.') >= 0) { return Double.valueOf(str); } return Long.valueOf(str); } } PARSER_END(GroupingParser) TOKEN : { (["l","L"])? | (["l","L"])? | (["l","L"])?> | <#DECIMAL: ["1"-"9"] (["0"-"9"])*> | <#HEX: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+> | <#OCTAL: "0" (["0"-"7"])*> | )? (["f","F","d","D"])?> | <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+> } // // NOTE: Whenever you add a new token, you need to also add it do the identifier() rule at the bottom of this grammar. // NOTE: Failure to do so will cause the token image to become a reserved word. To prevent regression on this, add the // NOTE: new token to the GroupingParserTestCase#requireThatTokenImagesAreNotReservedWords() test. // TOKEN : { | | | | | | | | | | | | | | | "> | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } // -------------------------------------------------------------------------------- // // Production rules. // // -------------------------------------------------------------------------------- List requestList() : { List lst = new LinkedList(); GroupingOperation val; } { ( space() val = root() { lst.add(val); } ( scolon() val = root() { lst.add(val); } )* ) { return lst;} } GroupingOperation request() : { GroupingOperation val; } { ( space() val = root() ) { return val; } } GroupingOperation root() : { String str; GroupingOperation ret; } { ( ret = operation(null) [ lbrace() str = where() rbrace() { GroupingOperation grp = new AllOperation(); grp.setWhere(str); grp.addChild(ret); ret = grp; } ] ) { return ret; } } GroupingOperation operation(GroupingOperation parent) : { GroupingOperation ret; } { ( ret = allOperation(parent) | ret = eachOperation(parent) ) { return ret; } } GroupingOperation allOperation(GroupingOperation parent) : { GroupingOperation ret; } { ( { ret = new AllOperation(); if (parent != null) { parent.addChild(ret); } } lbrace() operationBody(ret) rbrace() ) { return ret; } } GroupingOperation eachOperation(GroupingOperation parent) : { String str; GroupingOperation ret; } { ( { ret = new EachOperation(); if (parent != null) { parent.addChild(ret); } } lbrace() operationBody(ret) rbrace() [ lbrace() str = string() rbrace() { ret.setLabel(str); } ] ) { return ret; } } void operationBody(GroupingOperation parent) : { String str; Number num; GroupingExpression exp; List lst; } { [ lbrace() exp = exp(parent) rbrace() { parent.setGroupBy(exp); } ] ( ( lbrace() num = number() rbrace() { parent.setAccuracy(num.doubleValue()); } ) | ( lbrace() str = identifier() comma() exp = exp(parent) rbrace() { parent.putAlias(str, exp); } ) | ( lbrace() str = identifier() rbrace() { parent.addHint(str); } ) | ( lbrace() num = number() rbrace() { parent.setMax(num.intValue()); } ) | ( lbrace() lst = expList(parent) rbrace() { parent.addOrderBy(lst); } ) | ( lbrace() lst = expList(parent) rbrace() { parent.addOutputs(lst); } ) | ( lbrace() num = number() rbrace() { parent.setPrecision(num.intValue()); } ) | ( lbrace() str = where() rbrace() { parent.setWhere(str); } ) )* ( operation(parent) )* } String where() : { StringBuilder ret = new StringBuilder(); String str; } { ( [ { ret.append(token.image); } ] str = identifier() { ret.append(str); } ) { return ret.toString(); } } List expList(GroupingOperation grp) : { GroupingExpression exp; List ret = new LinkedList(); } { ( exp = exp(grp) { ret.add(exp); } ( comma() exp = exp(grp) { ret.add(exp); } )* ) { return ret; } } GroupingExpression exp(GroupingOperation grp) : { String str; boolean neg = false; GroupingExpression exp; } { ( [ add() | sub() { neg = true; } ] exp = expAlias(grp) { if (neg) { exp = new NegFunction(exp); } } [ lbrace() str = string() rbrace() { exp.setLabel(str); } ] ) { return exp; } } GroupingExpression expAlias(GroupingOperation grp) : { String str; GroupingExpression exp; } { ( ( str = identifier() [ eq() exp = expMath(grp) { grp.putAlias(str, exp); } ] { exp = grp.getAlias(str); } ) | ( exp = expMath(grp) ) ) { return exp; } } GroupingExpression expMath(GroupingOperation grp) : { MathResolver.Type type = MathResolver.Type.ADD; MathResolver math = new MathResolver(); GroupingExpression exp; } { ( exp = value(grp) { math.push(type, exp); } ( ( add() { type = MathResolver.Type.ADD; } | div() { type = MathResolver.Type.DIV; } | mod() { type = MathResolver.Type.MOD; } | mul() { type = MathResolver.Type.MUL; } | sub() { type = MathResolver.Type.SUB; } ) exp = value(grp) { math.push(type, exp); } )* ) { return math.resolve(); } } GroupingExpression value(GroupingOperation grp) : { GroupingExpression exp; } { ( LOOKAHEAD(2) ( ( lbrace() exp = exp(grp) rbrace() ) | exp = addFunction(grp) | exp = andFunction(grp) | exp = attributeFunction() | exp = avgExpression(grp) | exp = catFunction(grp) | exp = constantValue() | exp = countAggregator() | exp = debugWaitFunction(grp) | exp = divFunction(grp) | exp = docIdNsSpecificValue() | exp = fixedWidthFunction(grp) | exp = mathFunction(grp) | exp = maxExpression(grp) | exp = md5Function(grp) | exp = minExpression(grp) | exp = modFunction(grp) | exp = mulFunction(grp) | exp = negFunction(grp) | exp = normalizeSubjectFunction(grp) | exp = nowFunction() | exp = orFunction(grp) | exp = predefinedFunction(grp) | exp = relevanceValue() | exp = reverseFunction(grp) | exp = sizeFunction(grp) | exp = sortFunction(grp) | exp = arrayAtLookup(grp) | exp = interpolatedLookup(grp) | exp = stddevAggregator(grp) | exp = stringValue() | exp = strCatFunction(grp) | exp = strLenFunction(grp) | exp = subFunction(grp) | exp = sumAggregator(grp) | exp = summaryValue() | exp = timeFunction(grp) | exp = toDoubleFunction(grp) | exp = toLongFunction(grp) | exp = toRawFunction(grp) | exp = toStringFunction(grp) | exp = ucaFunction(grp) | exp = xorExpression(grp) | exp = xorBitFunction(grp) | exp = zcurveFunction(grp) ) | ( exp = attributeValue() ) ) { return exp; } } AddFunction addFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new AddFunction(arg1, arg2); return new AddFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } AndFunction andFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new AndFunction(arg1, arg2); return new AndFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } AttributeValue attributeValue() : { StringBuilder prefix = new StringBuilder(); StringBuilder suffix = new StringBuilder(); String str; String key = null; AttributeFunction keySourceAttr = null; } { ( str = identifier() { prefix.append(str); } ( LOOKAHEAD(2) { prefix.append(token.image); } ( str = identifier() { prefix.append(str); } ) )* ( LOOKAHEAD(3) ( lcurly() key = string() rcurly() ) | ( lcurly() keySourceAttr = attributeFunction() rcurly() ) )? ( { suffix.append(token.image); } ( str = identifier() { suffix.append(str); } ) )* ) { if (key != null) { return AttributeMapLookupValue.fromKey(prefix.toString(), key, suffix.toString()); } else if (keySourceAttr != null) { return AttributeMapLookupValue.fromKeySourceAttribute(prefix.toString(), keySourceAttr.getAttributeName(), suffix.toString()); } else { prefix.append(suffix.toString()); return new AttributeValue(prefix.toString()); } } } AttributeFunction attributeFunction() : { AttributeValue val; } { ( lbrace() val = attributeValue() rbrace() ) { return new AttributeFunction(val.getAttributeName()); } } ArrayAtLookup arrayAtLookup(GroupingOperation parent) : { AttributeValue val = null; GroupingExpression arg2 = null; } { ( lbrace() val = attributeValue() comma() arg2 = exp(parent) rbrace() ) { return new ArrayAtLookup(val.getAttributeName(), arg2); } } InterpolatedLookup interpolatedLookup(GroupingOperation parent) : { AttributeValue val = null; GroupingExpression arg2 = null; } { ( lbrace() val = attributeValue() comma() arg2 = exp(parent) rbrace() ) { return new InterpolatedLookup(val.getAttributeName(), arg2); } } GroupingExpression avgExpression(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2 = null; } { ( lbrace() arg1 = exp(grp) [ comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] ] rbrace() ) { if (arg2 == null) return new AvgAggregator(arg1); if (argN == null) return new AvgFunction(arg1, arg2); return new AvgFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } CatFunction catFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new CatFunction(arg1, arg2); return new CatFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } ConstantValue constantValue() : { Number num; } { ( num = number() ) { return num instanceof Double ? new DoubleValue((Double)num) : new LongValue((Long)num); } } ConstantValue constantValueSigned() : { Number num; } { ( num = signedNumber() ) { return num instanceof Double ? new DoubleValue((Double)num) : new LongValue((Long)num); } } InfiniteValue infiniteNegativeValue() : { } { ( neginf() { return new InfiniteValue(new Infinite(true)); } ) } InfiniteValue infinitePositiveValue() : { } { ( inf() { return new InfiniteValue(new Infinite(false)); } ) } CountAggregator countAggregator() : { } { ( lbrace() rbrace() ) { return new CountAggregator(); } } DebugWaitFunction debugWaitFunction(GroupingOperation grp) : { GroupingExpression arg; Number waitTime; BooleanValue busy; } { ( lbrace() arg = exp(grp) comma() waitTime = number() comma() busy = booleanValue() rbrace() ) { return new DebugWaitFunction(arg, new DoubleValue(waitTime.doubleValue()), busy); } } DivFunction divFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { (
lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new DivFunction(arg1, arg2); return new DivFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } DocIdNsSpecificValue docIdNsSpecificValue() : { } { ( lbrace() rbrace() ) { return new DocIdNsSpecificValue(); } } FixedWidthFunction fixedWidthFunction(GroupingOperation grp) : { GroupingExpression exp; Number num; } { ( lbrace() exp = exp(grp) comma() num = number() rbrace() ) { return new FixedWidthFunction(exp, num); } } GroupingExpression maxExpression(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2 = null; } { ( lbrace() arg1 = exp(grp) [ comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] ] rbrace() ) { if (arg2 == null) return new MaxAggregator(arg1); if (argN == null) return new MaxFunction(arg1, arg2); return new MaxFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } GroupingExpression md5Function(GroupingOperation grp) : { GroupingExpression exp; Number num; } { ( lbrace() exp = exp(grp) comma() num = number() rbrace() ) { return new Md5Function(exp, num.intValue()); } } GroupingExpression minExpression(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2 = null; } { ( lbrace() arg1 = exp(grp) [ comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] ] rbrace() ) { if (arg2 == null) return new MinAggregator(arg1); if (argN == null) return new MinFunction(arg1, arg2); return new MinFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } ModFunction modFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new ModFunction(arg1, arg2); return new ModFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } MulFunction mulFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new MulFunction(arg1, arg2); return new MulFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } NegFunction negFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new NegFunction(exp); } } NormalizeSubjectFunction normalizeSubjectFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new NormalizeSubjectFunction(exp); } } NowFunction nowFunction() : { } { ( lbrace() rbrace() ) { return new NowFunction(); } } OrFunction orFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new OrFunction(arg1, arg2); return new OrFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } PredefinedFunction predefinedFunction(GroupingOperation grp) : { GroupingExpression exp; BucketResolver resolver = new BucketResolver(); } { ( lbrace() exp = exp(grp) comma() bucket(grp, resolver) ( comma() bucket(grp, resolver) )* rbrace() ) { return resolver.resolve(exp); } } RelevanceValue relevanceValue() : { } { ( lbrace() rbrace() ) { return new RelevanceValue(); } } ReverseFunction reverseFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new ReverseFunction(exp); } } SizeFunction sizeFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new SizeFunction(exp); } } SortFunction sortFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new SortFunction(exp); } } StringValue stringValue() : { String str; } { ( { str = UnicodeUtilities.unquote(token.image); } space() ) { return new StringValue(str); } } RawValue rawValue(GroupingOperation grp) : { RawBuffer buffer = new RawBuffer(); } { ( lcurly() byteValue(buffer) ( comma() byteValue(buffer) )* rcurly() ) { return new RawValue(buffer); } } StandardDeviationAggregator stddevAggregator(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new StandardDeviationAggregator(exp); } } StringValue stringValueUnquoted() : { String str; } { ( str = string() ) { return new StringValue(str); } } StrCatFunction strCatFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new StrCatFunction(arg1, arg2); return new StrCatFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } StrLenFunction strLenFunction(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new StrLenFunction(exp); } } SubFunction subFunction(GroupingOperation grp) : { List argN = null; GroupingExpression arg1, arg2; } { ( lbrace() arg1 = exp(grp) comma() arg2 = exp(grp) [ comma() argN = expList(grp) ] rbrace() ) { if (argN == null) return new SubFunction(arg1, arg2); return new SubFunction(arg1, arg2, argN.toArray(new GroupingExpression[argN.size()])); } } SumAggregator sumAggregator(GroupingOperation grp) : { GroupingExpression exp; } { ( lbrace() exp = exp(grp) rbrace() ) { return new SumAggregator(exp); } } SummaryValue summaryValue() : { String str = null; } { ( lbrace() [ str = string() ] rbrace() ) { return str == null ? new SummaryValue() : new SummaryValue(str); } } FunctionNode timeFunction(GroupingOperation grp) : { TimeFunctions.Type type; GroupingExpression exp; } { (