public virtual void Visit(KeyValuePairExpr expr) { }
private Expr ParseMapProjectionExpr(Expr prev) { var bracket = Match("{"); var projections = new List <Expr>(); while (true) { var token = GetToken(); if (token.Kind == "}") { Match("}"); break; } string id = null; Expr projection; if (token.Kind == "}") { Match("}"); break; } if (token.Kind == "...") { var ellipsis = Match("..."); var next = GetToken(); projection = new SpreadExpr(GetLocation(ellipsis), ParseExpr()); } else if (token.Kind == "$") { var dollar = Match("$"); var dollarLocation = GetLocation(dollar); id = Match("ID").Text; projection = new KeyValuePairExpr(dollarLocation, id, new VariableExpr(dollarLocation, id)); } else { var idToken = MatchAny(new [] { "STRING", "ID" }); var idLocation = GetLocation(idToken); id = idToken.Text; var curr = GetToken(); if (curr.Kind == ":") { Match(":"); projection = new KeyValuePairExpr(idLocation, id, ParseExpr()); } else if (curr.Kind == "{") { // These are all equivalent: // foo: foo | { a, b, c } // foo | { a, b, c } // foo { a, b, c } MatchOptional("|"); var rhs = new ChainExpr( new KeyExpr(idLocation, prev, id), ParseExpr(), ChainBehavior.ToMultipleIfArray); projection = new KeyValuePairExpr(idLocation, id, rhs); } else if (curr.Kind == "(") { // key(a: 123) => key: key(a:123) var keyExpr = new KeyExpr(idLocation, prev, id); var rhs = ParseChainRemainder(keyExpr); projection = new KeyValuePairExpr(idLocation, id, rhs); } else if (curr.Kind == "[?") { // x[? filter] => x: x[? filter] var keyExpr = new KeyExpr(idLocation, prev, id); var rhs = ParseChainRemainder(keyExpr); projection = new KeyValuePairExpr(idLocation, id, rhs); } else if (curr.Kind == "[") { // x[5] => x: x[5] var keyExpr = new KeyExpr(idLocation, prev, id); var rhs = ParseChainRemainder(keyExpr); projection = new KeyValuePairExpr(idLocation, id, rhs); } else if (curr.Kind == "|") { // These are all equivalent: // foo: foo | { a, b, c } // foo | { a, b, c } // foo { a, b, c } MatchOptional("|"); var rhs = new ChainExpr( new KeyExpr(idLocation, prev, id), ParseExpr(), ChainBehavior.OneToOne); projection = new KeyValuePairExpr(idLocation, id, rhs); } else if (curr.Kind == "|<") { // This is another shorthand for filtring an array of objects. These are equivalent: /// foo: foo |< { a, b, c } /// foo |< { a, b, c} Match("|<"); var rhs = new ChainExpr( new KeyExpr(idLocation, prev, id), ParseExpr(), ChainBehavior.ToMultiple); projection = new KeyValuePairExpr(idLocation, id, rhs); } else { projection = new KeyValuePairExpr(idLocation, id, new KeyExpr(idLocation, null, id)); } } projections.Add(projection); var tok = MatchAny(new [] { ",", "}" }); if (tok.Kind == "}") { break; } } return(new MapProjectionExpr(GetLocation(bracket), prev, projections)); }