github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/gql/parser.go (about)

     1  /*
     2   * Copyright 2015-2018 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package gql
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"sort"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"github.com/dgraph-io/dgraph/lex"
    27  	"github.com/dgraph-io/dgraph/protos/pb"
    28  	"github.com/dgraph-io/dgraph/x"
    29  	"github.com/golang/glog"
    30  	"github.com/pkg/errors"
    31  )
    32  
    33  const (
    34  	uidFunc   = "uid"
    35  	valueFunc = "val"
    36  	typFunc   = "type"
    37  	lenFunc   = "len"
    38  	countFunc = "count"
    39  )
    40  
    41  // GraphQuery stores the parsed Query in a tree format. This gets converted to
    42  // pb.y used query.SubGraph before processing the query.
    43  type GraphQuery struct {
    44  	UID        []uint64
    45  	Attr       string
    46  	Langs      []string
    47  	Alias      string
    48  	IsCount    bool
    49  	IsInternal bool
    50  	IsGroupby  bool
    51  	Var        string
    52  	NeedsVar   []VarContext
    53  	Func       *Function
    54  	Expand     string // Which variable to expand with.
    55  
    56  	Args map[string]string
    57  	// Query can have multiple sort parameters.
    58  	Order            []*pb.Order
    59  	Children         []*GraphQuery
    60  	Filter           *FilterTree
    61  	MathExp          *MathTree
    62  	Normalize        bool
    63  	Recurse          bool
    64  	RecurseArgs      RecurseArgs
    65  	ShortestPathArgs ShortestPathArgs
    66  	Cascade          bool
    67  	IgnoreReflex     bool
    68  	Facets           *pb.FacetParams
    69  	FacetsFilter     *FilterTree
    70  	GroupbyAttrs     []GroupByAttr
    71  	FacetVar         map[string]string
    72  	FacetOrder       string
    73  	FacetDesc        bool
    74  
    75  	// Internal fields below.
    76  	// If gq.fragment is nonempty, then it is a fragment reference / spread.
    77  	fragment string
    78  
    79  	// Indicates whether count of uids is requested as a child node. If there
    80  	// is an alias, then UidCountAlias will be set (otherwise it will be the
    81  	// empty string).
    82  	UidCount      bool
    83  	UidCountAlias string
    84  
    85  	// True for blocks that don't have a starting function and hence no starting nodes. They are
    86  	// used to aggregate and get variables defined in another block.
    87  	IsEmpty bool
    88  }
    89  
    90  // RecurseArgs stores the arguments needed to process the @recurse directive.
    91  type RecurseArgs struct {
    92  	Depth     uint64
    93  	AllowLoop bool
    94  }
    95  
    96  // ShortestPathArgs stores the arguments needed to process the shortest path query.
    97  type ShortestPathArgs struct {
    98  	// From, To can have a uid or a uid function as the argument.
    99  	// 1. from: 0x01
   100  	// 2. from: uid(0x01)
   101  	// 3. from: uid(p) // a variable
   102  	From *Function
   103  	To   *Function
   104  }
   105  
   106  // GroupByAttr stores the arguments needed to process the @groupby directive.
   107  type GroupByAttr struct {
   108  	Attr  string
   109  	Alias string
   110  	Langs []string
   111  }
   112  
   113  // pair denotes the key value pair that is part of the GraphQL query root in parenthesis.
   114  type pair struct {
   115  	Key string
   116  	Val string
   117  }
   118  
   119  // fragmentNode is an internal structure for doing dfs on fragments.
   120  type fragmentNode struct {
   121  	Name    string
   122  	Gq      *GraphQuery
   123  	Entered bool // Entered in dfs.
   124  	Exited  bool // Exited in dfs.
   125  }
   126  
   127  // fragmentMap is used to associate fragment names to their corresponding fragmentNode.
   128  type fragmentMap map[string]*fragmentNode
   129  
   130  const (
   131  	AnyVar   = 0
   132  	UidVar   = 1
   133  	ValueVar = 2
   134  	ListVar  = 3
   135  )
   136  
   137  // VarContext stores information about the vars needed to complete a query.
   138  type VarContext struct {
   139  	Name string
   140  	Typ  int //  1 for UID vars, 2 for value vars
   141  }
   142  
   143  // varInfo holds information on GQL variables.
   144  type varInfo struct {
   145  	Value string
   146  	Type  string
   147  }
   148  
   149  // varMap is a map with key as GQL variable name.
   150  type varMap map[string]varInfo
   151  
   152  // FilterTree is the result of parsing the filter directive.
   153  // Either you can have `Op and Children` on non-leaf nodes
   154  // Or Func at leaf nodes.
   155  type FilterTree struct {
   156  	Op    string
   157  	Child []*FilterTree
   158  	Func  *Function
   159  }
   160  
   161  // Arg stores an argument to a function.
   162  type Arg struct {
   163  	Value        string
   164  	IsValueVar   bool // If argument is val(a), e.g. eq(name, val(a))
   165  	IsGraphQLVar bool
   166  }
   167  
   168  // Function holds the information about gql functions.
   169  type Function struct {
   170  	Attr       string
   171  	Lang       string // language of the attribute value
   172  	Name       string // Specifies the name of the function.
   173  	Args       []Arg  // Contains the arguments of the function.
   174  	UID        []uint64
   175  	NeedsVar   []VarContext // If the function requires some variable
   176  	IsCount    bool         // gt(count(friends),0)
   177  	IsValueVar bool         // eq(val(s), 5)
   178  	IsLenVar   bool         // eq(len(s), 5)
   179  }
   180  
   181  // filterOpPrecedence is a map from filterOp (a string) to its precedence.
   182  var filterOpPrecedence = map[string]int{
   183  	"not": 3,
   184  	"and": 2,
   185  	"or":  1,
   186  }
   187  var mathOpPrecedence = map[string]int{
   188  	"u-":      500,
   189  	"floor":   105,
   190  	"ceil":    104,
   191  	"since":   103,
   192  	"exp":     100,
   193  	"ln":      99,
   194  	"sqrt":    98,
   195  	"cond":    90,
   196  	"pow":     89,
   197  	"logbase": 88,
   198  	"max":     85,
   199  	"min":     84,
   200  
   201  	"/": 50,
   202  	"*": 49,
   203  	"%": 48,
   204  	"-": 47,
   205  	"+": 46,
   206  
   207  	"<":  10,
   208  	">":  9,
   209  	"<=": 8,
   210  	">=": 7,
   211  	"==": 6,
   212  	"!=": 5,
   213  }
   214  
   215  // IsAggregator returns true if the function name is an aggregation function.
   216  func (f *Function) IsAggregator() bool {
   217  	return isAggregator(f.Name)
   218  }
   219  
   220  // IsPasswordVerifier returns true if the function name is "checkpwd".
   221  func (f *Function) IsPasswordVerifier() bool {
   222  	return f.Name == "checkpwd"
   223  }
   224  
   225  // DebugPrint is useful for debugging.
   226  func (gq *GraphQuery) DebugPrint(prefix string) {
   227  	glog.Infof("%s[%x %q %q]\n", prefix, gq.UID, gq.Attr, gq.Alias)
   228  	for _, c := range gq.Children {
   229  		c.DebugPrint(prefix + "|->")
   230  	}
   231  }
   232  
   233  func (gq *GraphQuery) isFragment() bool {
   234  	return gq.fragment != ""
   235  }
   236  
   237  func (fn *fragmentNode) expand(fmap fragmentMap) error {
   238  	if fn.Exited {
   239  		// This fragment node has already been expanded.
   240  		return nil
   241  	}
   242  	if fn.Entered {
   243  		return errors.Errorf("Cycle detected: %s", fn.Name)
   244  	}
   245  	fn.Entered = true
   246  	if err := fn.Gq.expandFragments(fmap); err != nil {
   247  		return err
   248  	}
   249  	fn.Exited = true
   250  	return nil
   251  }
   252  
   253  func (gq *GraphQuery) expandFragments(fmap fragmentMap) error {
   254  	// We have to make a copy of children to preserve order and replace
   255  	// fragment references with fragment content. The copy is newChildren.
   256  	var newChildren []*GraphQuery
   257  	// Expand non-fragments. Do not append to gq.Children.
   258  	for _, child := range gq.Children {
   259  		if child.isFragment() {
   260  			fname := child.fragment // Name of fragment being referenced.
   261  			fchild := fmap[fname]
   262  			if fchild == nil {
   263  				return errors.Errorf("Missing fragment: %s", fname)
   264  			}
   265  			if err := fchild.expand(fmap); err != nil {
   266  				return err
   267  			}
   268  			newChildren = append(newChildren, fchild.Gq.Children...)
   269  		} else {
   270  			if err := child.expandFragments(fmap); err != nil {
   271  				return err
   272  			}
   273  			newChildren = append(newChildren, child)
   274  		}
   275  	}
   276  	gq.Children = newChildren
   277  	return nil
   278  }
   279  
   280  func convertToVarMap(variables map[string]string) (vm varMap) {
   281  	vm = make(map[string]varInfo)
   282  	for k, v := range variables {
   283  		vm[k] = varInfo{
   284  			Value: v,
   285  		}
   286  	}
   287  	return vm
   288  }
   289  
   290  // Request stores the query text and the variable mapping.
   291  type Request struct {
   292  	Str       string
   293  	Variables map[string]string
   294  }
   295  
   296  func checkValueType(vm varMap) error {
   297  	for k, v := range vm {
   298  		typ := v.Type
   299  
   300  		if len(typ) == 0 {
   301  			return errors.Errorf("Type of variable %v not specified", k)
   302  		}
   303  
   304  		// Ensure value is not nil if the variable is required.
   305  		if typ[len(typ)-1] == '!' {
   306  			if v.Value == "" {
   307  				return errors.Errorf("Variable %v should be initialised", k)
   308  			}
   309  			typ = typ[:len(typ)-1]
   310  		}
   311  
   312  		// Type check the values.
   313  		if v.Value != "" {
   314  			switch typ {
   315  			case "int":
   316  				{
   317  					if _, err := strconv.ParseInt(v.Value, 0, 64); err != nil {
   318  						return errors.Wrapf(err, "Expected an int but got %v", v.Value)
   319  					}
   320  				}
   321  			case "float":
   322  				{
   323  					if _, err := strconv.ParseFloat(v.Value, 64); err != nil {
   324  						return errors.Wrapf(err, "Expected a float but got %v", v.Value)
   325  					}
   326  				}
   327  			case "bool":
   328  				{
   329  					if _, err := strconv.ParseBool(v.Value); err != nil {
   330  						return errors.Wrapf(err, "Expected a bool but got %v", v.Value)
   331  					}
   332  				}
   333  			case "string": // Value is a valid string. No checks required.
   334  			default:
   335  				return errors.Errorf("Type %q not supported", typ)
   336  			}
   337  		}
   338  	}
   339  
   340  	return nil
   341  }
   342  
   343  func substituteVar(f string, res *string, vmap varMap) error {
   344  	if len(f) > 0 && f[0] == '$' {
   345  		va, ok := vmap[f]
   346  		if !ok || va.Type == "" {
   347  			return errors.Errorf("Variable not defined %v", f)
   348  		}
   349  		*res = va.Value
   350  	}
   351  	return nil
   352  }
   353  
   354  func substituteVariables(gq *GraphQuery, vmap varMap) error {
   355  	for k, v := range gq.Args {
   356  		// v won't be empty as its handled in parseGqlVariables.
   357  		val := gq.Args[k]
   358  		if err := substituteVar(v, &val, vmap); err != nil {
   359  			return err
   360  		}
   361  		gq.Args[k] = val
   362  	}
   363  
   364  	idVal, ok := gq.Args["id"]
   365  	if ok && len(gq.UID) == 0 {
   366  		if idVal == "" {
   367  			return errors.Errorf("Id can't be empty")
   368  		}
   369  		uids, err := parseID(idVal)
   370  		if err != nil {
   371  			return err
   372  		}
   373  		gq.UID = append(gq.UID, uids...)
   374  		// Deleting it here because we don't need to fill it in query.go.
   375  		delete(gq.Args, "id")
   376  	}
   377  
   378  	if gq.Func != nil {
   379  		if err := substituteVar(gq.Func.Attr, &gq.Func.Attr, vmap); err != nil {
   380  			return err
   381  		}
   382  
   383  		for idx, v := range gq.Func.Args {
   384  			if !v.IsGraphQLVar {
   385  				continue
   386  			}
   387  			if err := substituteVar(v.Value, &gq.Func.Args[idx].Value, vmap); err != nil {
   388  				return err
   389  			}
   390  			if gq.Func.Name == "regexp" {
   391  				// Value should have been populated from the map that the user gave us in the
   392  				// GraphQL variable map. Let's parse the expression and flags from the variable
   393  				// string.
   394  				ra, err := parseRegexArgs(gq.Func.Args[idx].Value)
   395  				if err != nil {
   396  					return err
   397  				}
   398  				// We modify the value of this arg and add a new arg for the flags. Regex functions
   399  				// should have two args.
   400  				gq.Func.Args[idx].Value = ra.expr
   401  				gq.Func.Args = append(gq.Func.Args, Arg{Value: ra.flags})
   402  			}
   403  		}
   404  	}
   405  
   406  	for _, child := range gq.Children {
   407  		if err := substituteVariables(child, vmap); err != nil {
   408  			return err
   409  		}
   410  	}
   411  	if gq.Filter != nil {
   412  		if err := substituteVariablesFilter(gq.Filter, vmap); err != nil {
   413  			return err
   414  		}
   415  	}
   416  	return nil
   417  }
   418  
   419  func substituteVariablesFilter(f *FilterTree, vmap varMap) error {
   420  	if f.Func != nil {
   421  		if err := substituteVar(f.Func.Attr, &f.Func.Attr, vmap); err != nil {
   422  			return err
   423  		}
   424  
   425  		for idx, v := range f.Func.Args {
   426  			if f.Func.Name == uidFunc {
   427  				// This is to support GraphQL variables in uid functions.
   428  				idVal, ok := vmap[v.Value]
   429  				if !ok {
   430  					return errors.Errorf("Couldn't find value for GraphQL variable: [%s]", v.Value)
   431  				}
   432  				if idVal.Value == "" {
   433  					return errors.Errorf("Id can't be empty")
   434  				}
   435  				uids, err := parseID(idVal.Value)
   436  				if err != nil {
   437  					return err
   438  				}
   439  				f.Func.UID = append(f.Func.UID, uids...)
   440  				continue
   441  			}
   442  
   443  			if err := substituteVar(v.Value, &f.Func.Args[idx].Value, vmap); err != nil {
   444  				return err
   445  			}
   446  		}
   447  	}
   448  
   449  	for _, fChild := range f.Child {
   450  		if err := substituteVariablesFilter(fChild, vmap); err != nil {
   451  			return err
   452  		}
   453  	}
   454  	return nil
   455  }
   456  
   457  // Vars struct contains the list of variables defined and used by a
   458  // query block.
   459  type Vars struct {
   460  	Defines []string
   461  	Needs   []string
   462  }
   463  
   464  // Result struct contains the Query list, its corresponding variable use list
   465  // and the mutation block.
   466  type Result struct {
   467  	Query     []*GraphQuery
   468  	QueryVars []*Vars
   469  	Schema    *pb.SchemaRequest
   470  }
   471  
   472  // Parse initializes and runs the lexer. It also constructs the GraphQuery subgraph
   473  // from the lexed items.
   474  func Parse(r Request) (Result, error) {
   475  	return ParseWithNeedVars(r, nil)
   476  }
   477  
   478  // ParseWithNeedVars performs parsing of a query with given needVars.
   479  //
   480  // The needVars parameter is passed in the case of upsert block.
   481  // For example, when parsing the query block inside -
   482  // upsert {
   483  //   query {
   484  //     me(func: eq(email, "someone@gmail.com"), first: 1) {
   485  //       v as uid
   486  //     }
   487  //   }
   488  //
   489  //   mutation {
   490  //     set {
   491  //       uid(v) <name> "Some One" .
   492  //       uid(v) <email> "someone@gmail.com" .
   493  //     }
   494  //   }
   495  // }
   496  //
   497  // The variable name v needs to be passed through the needVars parameter. Otherwise, an error
   498  // is reported complaining that the variable v is defined but not used in the query block.
   499  func ParseWithNeedVars(r Request, needVars []string) (res Result, rerr error) {
   500  	query := r.Str
   501  	vmap := convertToVarMap(r.Variables)
   502  
   503  	var lexer lex.Lexer
   504  	lexer.Reset(query)
   505  	lexer.Run(lexTopLevel)
   506  	if err := lexer.ValidateResult(); err != nil {
   507  		return res, err
   508  	}
   509  
   510  	var qu *GraphQuery
   511  	it := lexer.NewIterator()
   512  	fmap := make(fragmentMap)
   513  	for it.Next() {
   514  		item := it.Item()
   515  		switch item.Typ {
   516  		case itemOpType:
   517  			if item.Val == "mutation" {
   518  				return res, item.Errorf("Mutation block no longer allowed.")
   519  			}
   520  			if item.Val == "schema" {
   521  				if res.Schema != nil {
   522  					return res, item.Errorf("Only one schema block allowed ")
   523  				}
   524  				if res.Query != nil {
   525  					return res, item.Errorf("Schema block is not allowed with query block")
   526  				}
   527  				if res.Schema, rerr = getSchema(it); rerr != nil {
   528  					return res, rerr
   529  				}
   530  			} else if item.Val == "fragment" {
   531  				// TODO(jchiu0): This is to be done in ParseSchema once it is ready.
   532  				fnode, rerr := getFragment(it)
   533  				if rerr != nil {
   534  					return res, rerr
   535  				}
   536  				fmap[fnode.Name] = fnode
   537  			} else if item.Val == "query" {
   538  				if res.Schema != nil {
   539  					return res, item.Errorf("Schema block is not allowed with query block")
   540  				}
   541  				if qu, rerr = getVariablesAndQuery(it, vmap); rerr != nil {
   542  					return res, rerr
   543  				}
   544  				res.Query = append(res.Query, qu)
   545  			}
   546  		case itemLeftCurl:
   547  			if qu, rerr = getQuery(it); rerr != nil {
   548  				return res, rerr
   549  			}
   550  			res.Query = append(res.Query, qu)
   551  		case itemName:
   552  			it.Prev()
   553  			if qu, rerr = getQuery(it); rerr != nil {
   554  				return res, rerr
   555  			}
   556  			res.Query = append(res.Query, qu)
   557  		}
   558  	}
   559  
   560  	if len(res.Query) != 0 {
   561  		res.QueryVars = make([]*Vars, 0, len(res.Query))
   562  		for i := 0; i < len(res.Query); i++ {
   563  			qu := res.Query[i]
   564  			// Try expanding fragments using fragment map.
   565  			if err := qu.expandFragments(fmap); err != nil {
   566  				return res, err
   567  			}
   568  
   569  			// Substitute all graphql variables with corresponding values
   570  			if err := substituteVariables(qu, vmap); err != nil {
   571  				return res, err
   572  			}
   573  
   574  			res.QueryVars = append(res.QueryVars, &Vars{})
   575  			// Collect vars used and defined in Result struct.
   576  			qu.collectVars(res.QueryVars[i])
   577  		}
   578  
   579  		allVars := res.QueryVars
   580  		// Add the variables that are needed outside the query block.
   581  		// For example, mutation block in upsert block will be using
   582  		// variables from the query block that is getting parsed here.
   583  		if len(needVars) != 0 {
   584  			allVars = append(allVars, &Vars{Needs: needVars})
   585  		}
   586  		if err := checkDependency(allVars); err != nil {
   587  			return res, err
   588  		}
   589  	}
   590  
   591  	if err := validateResult(&res); err != nil {
   592  		return res, err
   593  	}
   594  
   595  	return res, nil
   596  }
   597  
   598  func validateResult(res *Result) error {
   599  	seenQueryAliases := make(map[string]bool)
   600  	for _, q := range res.Query {
   601  		if q.Alias == "var" || q.Alias == "shortest" {
   602  			continue
   603  		}
   604  		if _, found := seenQueryAliases[q.Alias]; found {
   605  			return errors.Errorf("Duplicate aliases not allowed: %v", q.Alias)
   606  		}
   607  		seenQueryAliases[q.Alias] = true
   608  	}
   609  	return nil
   610  }
   611  
   612  func flatten(vl []*Vars) (needs []string, defines []string) {
   613  	needs, defines = make([]string, 0, 10), make([]string, 0, 10)
   614  	for _, it := range vl {
   615  		needs = append(needs, it.Needs...)
   616  		defines = append(defines, it.Defines...)
   617  	}
   618  	return
   619  }
   620  
   621  func checkDependency(vl []*Vars) error {
   622  	needs, defines := flatten(vl)
   623  
   624  	needs = x.RemoveDuplicates(needs)
   625  	lenBefore := len(defines)
   626  	defines = x.RemoveDuplicates(defines)
   627  
   628  	if len(defines) != lenBefore {
   629  		return errors.Errorf("Some variables are declared multiple times.")
   630  	}
   631  	if len(defines) > len(needs) {
   632  		return errors.Errorf("Some variables are defined but not used\nDefined:%v\nUsed:%v\n",
   633  			defines, needs)
   634  	}
   635  	if len(defines) < len(needs) {
   636  		return errors.Errorf("Some variables are used but not defined\nDefined:%v\nUsed:%v\n",
   637  			defines, needs)
   638  	}
   639  
   640  	for i := 0; i < len(defines); i++ {
   641  		if defines[i] != needs[i] {
   642  			return errors.Errorf("Variables are not used properly. \nDefined:%v\nUsed:%v\n",
   643  				defines, needs)
   644  		}
   645  	}
   646  	return nil
   647  }
   648  
   649  func (gq *GraphQuery) collectVars(v *Vars) {
   650  	if gq.Var != "" {
   651  		v.Defines = append(v.Defines, gq.Var)
   652  	}
   653  	if gq.FacetVar != nil {
   654  		for _, va := range gq.FacetVar {
   655  			v.Defines = append(v.Defines, va)
   656  		}
   657  	}
   658  	for _, va := range gq.NeedsVar {
   659  		v.Needs = append(v.Needs, va.Name)
   660  	}
   661  
   662  	for _, ch := range gq.Children {
   663  		ch.collectVars(v)
   664  	}
   665  	if gq.Filter != nil {
   666  		gq.Filter.collectVars(v)
   667  	}
   668  	if gq.MathExp != nil {
   669  		gq.MathExp.collectVars(v)
   670  	}
   671  
   672  	shortestPathFrom := gq.ShortestPathArgs.From
   673  	if shortestPathFrom != nil && len(shortestPathFrom.NeedsVar) > 0 {
   674  		v.Needs = append(v.Needs, shortestPathFrom.NeedsVar[0].Name)
   675  	}
   676  	shortestPathTo := gq.ShortestPathArgs.To
   677  	if shortestPathTo != nil && len(shortestPathTo.NeedsVar) > 0 {
   678  		v.Needs = append(v.Needs, shortestPathTo.NeedsVar[0].Name)
   679  	}
   680  }
   681  
   682  func (f *MathTree) collectVars(v *Vars) {
   683  	if f == nil {
   684  		return
   685  	}
   686  	if f.Var != "" {
   687  		v.Needs = append(v.Needs, f.Var)
   688  		return
   689  	}
   690  	for _, fch := range f.Child {
   691  		fch.collectVars(v)
   692  	}
   693  }
   694  
   695  func (f *FilterTree) collectVars(v *Vars) {
   696  	if f.Func != nil {
   697  		for _, va := range f.Func.NeedsVar {
   698  			v.Needs = append(v.Needs, va.Name)
   699  		}
   700  	}
   701  	for _, fch := range f.Child {
   702  		fch.collectVars(v)
   703  	}
   704  }
   705  
   706  func (f *FilterTree) hasVars() bool {
   707  	if (f.Func != nil) && (len(f.Func.NeedsVar) > 0) {
   708  		return true
   709  	}
   710  	for _, fch := range f.Child {
   711  		if fch.hasVars() {
   712  			return true
   713  		}
   714  	}
   715  	return false
   716  }
   717  
   718  // getVariablesAndQuery checks if the query has a variable list and stores it in
   719  // vmap. For variable list to be present, the query should have a name which is
   720  // also checked for. It also calls getQuery to create the GraphQuery object tree.
   721  func getVariablesAndQuery(it *lex.ItemIterator, vmap varMap) (gq *GraphQuery, rerr error) {
   722  	var name string
   723  L2:
   724  	for it.Next() {
   725  		item := it.Item()
   726  		switch item.Typ {
   727  		case itemName:
   728  			if name != "" {
   729  				return nil, item.Errorf("Multiple word query name not allowed.")
   730  			}
   731  			name = item.Val
   732  		case itemLeftRound:
   733  			if name == "" {
   734  				return nil, item.Errorf("Variables can be defined only in named queries.")
   735  			}
   736  
   737  			if rerr = parseGqlVariables(it, vmap); rerr != nil {
   738  				return nil, rerr
   739  			}
   740  
   741  			if rerr = checkValueType(vmap); rerr != nil {
   742  				return nil, rerr
   743  			}
   744  		case itemLeftCurl:
   745  			if gq, rerr = getQuery(it); rerr != nil {
   746  				return nil, rerr
   747  			}
   748  			break L2
   749  		}
   750  	}
   751  
   752  	return gq, nil
   753  }
   754  
   755  func parseRecurseArgs(it *lex.ItemIterator, gq *GraphQuery) error {
   756  	if ok := trySkipItemTyp(it, itemLeftRound); !ok {
   757  		// We don't have a (, we can return.
   758  		return nil
   759  	}
   760  
   761  	var key, val string
   762  	var ok bool
   763  	for it.Next() {
   764  		item := it.Item()
   765  		if item.Typ != itemName {
   766  			return item.Errorf("Expected key inside @recurse()")
   767  		}
   768  		key = strings.ToLower(item.Val)
   769  
   770  		if ok := trySkipItemTyp(it, itemColon); !ok {
   771  			return it.Errorf("Expected colon(:) after %s", key)
   772  		}
   773  
   774  		if item, ok = tryParseItemType(it, itemName); !ok {
   775  			return item.Errorf("Expected value inside @recurse() for key: %s", key)
   776  		}
   777  		val = item.Val
   778  
   779  		switch key {
   780  		case "depth":
   781  			depth, err := strconv.ParseUint(val, 0, 64)
   782  			if err != nil {
   783  				return err
   784  			}
   785  			gq.RecurseArgs.Depth = depth
   786  		case "loop":
   787  			allowLoop, err := strconv.ParseBool(val)
   788  			if err != nil {
   789  				return err
   790  			}
   791  			gq.RecurseArgs.AllowLoop = allowLoop
   792  		default:
   793  			return item.Errorf("Unexpected key: [%s] inside @recurse block", key)
   794  		}
   795  
   796  		if _, ok := tryParseItemType(it, itemRightRound); ok {
   797  			return nil
   798  		}
   799  
   800  		if _, ok := tryParseItemType(it, itemComma); !ok {
   801  			return it.Errorf("Expected comma after value: %s inside recurse block", val)
   802  		}
   803  	}
   804  	return nil
   805  }
   806  
   807  // getQuery creates a GraphQuery object tree by calling getRoot
   808  // and goDeep functions by looking at '{'.
   809  func getQuery(it *lex.ItemIterator) (gq *GraphQuery, rerr error) {
   810  	// First, get the root
   811  	gq, rerr = getRoot(it)
   812  	if rerr != nil {
   813  		return nil, rerr
   814  	}
   815  
   816  	var seenFilter bool
   817  L:
   818  	// Recurse to deeper levels through godeep.
   819  	if !it.Next() {
   820  		return nil, it.Errorf("Expecting more lexer items while parsing query")
   821  	}
   822  
   823  	item := it.Item()
   824  	if item.Typ == itemLeftCurl {
   825  		if rerr = godeep(it, gq); rerr != nil {
   826  			return nil, rerr
   827  		}
   828  	} else if item.Typ == itemAt {
   829  		it.Next()
   830  		item := it.Item()
   831  		if item.Typ == itemName {
   832  			switch strings.ToLower(item.Val) {
   833  			case "filter":
   834  				if seenFilter {
   835  					return nil, item.Errorf("Repeated filter at root")
   836  				}
   837  				seenFilter = true
   838  				filter, err := parseFilter(it)
   839  				if err != nil {
   840  					return nil, err
   841  				}
   842  				gq.Filter = filter
   843  
   844  			case "normalize":
   845  				gq.Normalize = true
   846  			case "cascade":
   847  				gq.Cascade = true
   848  			case "groupby":
   849  				gq.IsGroupby = true
   850  				if err := parseGroupby(it, gq); err != nil {
   851  					return nil, err
   852  				}
   853  			case "ignorereflex":
   854  				gq.IgnoreReflex = true
   855  			case "recurse":
   856  				gq.Recurse = true
   857  				if err := parseRecurseArgs(it, gq); err != nil {
   858  					return nil, err
   859  				}
   860  			default:
   861  				return nil, item.Errorf("Unknown directive [%s]", item.Val)
   862  			}
   863  			goto L
   864  		}
   865  	} else if item.Typ == itemRightCurl {
   866  		// Do nothing.
   867  	} else if item.Typ == itemName {
   868  		it.Prev()
   869  		return gq, nil
   870  	} else {
   871  		return nil, item.Errorf("Malformed Query. Missing {. Got %v", item.Val)
   872  	}
   873  
   874  	return gq, nil
   875  }
   876  
   877  // getFragment parses a fragment definition (not reference).
   878  func getFragment(it *lex.ItemIterator) (*fragmentNode, error) {
   879  	var name string
   880  	for it.Next() {
   881  		item := it.Item()
   882  		if item.Typ == itemName {
   883  			v := strings.TrimSpace(item.Val)
   884  			if len(v) > 0 && name == "" {
   885  				// Currently, we take the first nontrivial token as the
   886  				// fragment name and ignore everything after that until we see
   887  				// a left curl.
   888  				name = v
   889  			}
   890  		} else if item.Typ == itemLeftCurl {
   891  			break
   892  		} else {
   893  			return nil, item.Errorf("Unexpected item in fragment: %v %v", item.Typ, item.Val)
   894  		}
   895  	}
   896  	if name == "" {
   897  		return nil, it.Errorf("Empty fragment name")
   898  	}
   899  
   900  	gq := &GraphQuery{
   901  		Args: make(map[string]string),
   902  	}
   903  	if err := godeep(it, gq); err != nil {
   904  		return nil, err
   905  	}
   906  	fn := &fragmentNode{
   907  		Name: name,
   908  		Gq:   gq,
   909  	}
   910  	return fn, nil
   911  }
   912  
   913  // parses till rightSquare is found (parses [a, b]) excluding leftSquare
   914  // This function can be reused for query later
   915  func parseListItemNames(it *lex.ItemIterator) ([]string, error) {
   916  	var items []string
   917  	for it.Next() {
   918  		item := it.Item()
   919  		switch item.Typ {
   920  		case itemRightSquare:
   921  			return items, nil
   922  		case itemName:
   923  			val := collectName(it, item.Val)
   924  			items = append(items, val)
   925  		case itemComma:
   926  			it.Next()
   927  			item = it.Item()
   928  			if item.Typ != itemName {
   929  				return items, item.Errorf("Invalid scheam block")
   930  			}
   931  			val := collectName(it, item.Val)
   932  			items = append(items, val)
   933  		default:
   934  			return items, item.Errorf("Invalid schema block")
   935  		}
   936  	}
   937  	return items, it.Errorf("Expecting ] to end list but none was found")
   938  }
   939  
   940  // parseSchemaPredsOrTypes parses till rightround is found
   941  func parseSchemaPredsOrTypes(it *lex.ItemIterator, s *pb.SchemaRequest) error {
   942  	// pred or type should be followed by colon
   943  	it.Next()
   944  	item := it.Item()
   945  	if item.Typ != itemName && !(item.Val == "pred" || item.Val == "type") {
   946  		return item.Errorf("Invalid schema block")
   947  	}
   948  	parseTypes := false
   949  	if item.Val == "type" {
   950  		parseTypes = true
   951  	}
   952  
   953  	it.Next()
   954  	item = it.Item()
   955  	if item.Typ != itemColon {
   956  		return item.Errorf("Invalid schema block")
   957  	}
   958  
   959  	// can be a or [a,b]
   960  	it.Next()
   961  	item = it.Item()
   962  	if item.Typ == itemName {
   963  		if parseTypes {
   964  			s.Types = append(s.Types, item.Val)
   965  		} else {
   966  			s.Predicates = append(s.Predicates, item.Val)
   967  		}
   968  	} else if item.Typ == itemLeftSquare {
   969  		names, err := parseListItemNames(it)
   970  		if err != nil {
   971  			return err
   972  		}
   973  
   974  		if parseTypes {
   975  			s.Types = names
   976  		} else {
   977  			s.Predicates = names
   978  		}
   979  	} else {
   980  		return item.Errorf("Invalid schema block")
   981  	}
   982  
   983  	it.Next()
   984  	item = it.Item()
   985  	if item.Typ == itemRightRound {
   986  		return nil
   987  	}
   988  	return item.Errorf("Invalid schema blocks")
   989  }
   990  
   991  // parses till rightcurl is found
   992  func parseSchemaFields(it *lex.ItemIterator, s *pb.SchemaRequest) error {
   993  	for it.Next() {
   994  		item := it.Item()
   995  		switch item.Typ {
   996  		case itemRightCurl:
   997  			return nil
   998  		case itemName:
   999  			s.Fields = append(s.Fields, item.Val)
  1000  		default:
  1001  			return item.Errorf("Invalid schema block.")
  1002  		}
  1003  	}
  1004  	return it.Errorf("Expecting } to end fields list, but none was found")
  1005  }
  1006  
  1007  func getSchema(it *lex.ItemIterator) (*pb.SchemaRequest, error) {
  1008  	var s pb.SchemaRequest
  1009  	leftRoundSeen := false
  1010  	for it.Next() {
  1011  		item := it.Item()
  1012  		switch item.Typ {
  1013  		case itemLeftCurl:
  1014  			if err := parseSchemaFields(it, &s); err != nil {
  1015  				return nil, err
  1016  			}
  1017  			return &s, nil
  1018  		case itemLeftRound:
  1019  			if leftRoundSeen {
  1020  				return nil, item.Errorf("Too many left rounds in schema block")
  1021  			}
  1022  			leftRoundSeen = true
  1023  			if err := parseSchemaPredsOrTypes(it, &s); err != nil {
  1024  				return nil, err
  1025  			}
  1026  		default:
  1027  			return nil, item.Errorf("Invalid schema block")
  1028  		}
  1029  	}
  1030  	return nil, it.Errorf("Invalid schema block.")
  1031  }
  1032  
  1033  // parseGqlVariables parses the the graphQL variable declaration.
  1034  func parseGqlVariables(it *lex.ItemIterator, vmap varMap) error {
  1035  	expectArg := true
  1036  	for it.Next() {
  1037  		var varName string
  1038  		// Get variable name.
  1039  		item := it.Item()
  1040  		if item.Typ == itemDollar {
  1041  			if !expectArg {
  1042  				return item.Errorf("Missing comma in var declaration")
  1043  			}
  1044  			it.Next()
  1045  			item = it.Item()
  1046  			if item.Typ == itemName {
  1047  				varName = fmt.Sprintf("$%s", item.Val)
  1048  			} else {
  1049  				return item.Errorf("Expecting a variable name. Got: %v", item)
  1050  			}
  1051  		} else if item.Typ == itemRightRound {
  1052  			if expectArg {
  1053  				return item.Errorf("Invalid comma in var block")
  1054  			}
  1055  			break
  1056  		} else if item.Typ == itemComma {
  1057  			if expectArg {
  1058  				return item.Errorf("Invalid comma in var block")
  1059  			}
  1060  			expectArg = true
  1061  			continue
  1062  		} else {
  1063  			return item.Errorf("Unexpected item in place of variable. Got: %v %v", item,
  1064  				item.Typ == itemDollar)
  1065  		}
  1066  
  1067  		it.Next()
  1068  		item = it.Item()
  1069  		if item.Typ != itemColon {
  1070  			return item.Errorf("Expecting a colon. Got: %v", item)
  1071  		}
  1072  
  1073  		// Get variable type.
  1074  		it.Next()
  1075  		item = it.Item()
  1076  		if item.Typ != itemName {
  1077  			return item.Errorf("Expecting a variable type. Got: %v", item)
  1078  		}
  1079  
  1080  		// Ensure that the type is not nil.
  1081  		varType := item.Val
  1082  		if varType == "" {
  1083  			return item.Errorf("Type of a variable can't be empty")
  1084  		}
  1085  		it.Next()
  1086  		item = it.Item()
  1087  		if item.Typ == itemMathOp && item.Val == "!" {
  1088  			varType += item.Val
  1089  			it.Next()
  1090  			item = it.Item()
  1091  		}
  1092  		// Insert the variable into the map. The variable might already be defiend
  1093  		// in the variable list passed with the query.
  1094  		if _, ok := vmap[varName]; ok {
  1095  			vmap[varName] = varInfo{
  1096  				Value: vmap[varName].Value,
  1097  				Type:  varType,
  1098  			}
  1099  		} else {
  1100  			vmap[varName] = varInfo{
  1101  				Type: varType,
  1102  			}
  1103  		}
  1104  
  1105  		// Check for '=' sign and optional default value.
  1106  		if item.Typ == itemEqual {
  1107  			it.Next()
  1108  			it := it.Item()
  1109  			if it.Typ != itemName {
  1110  				return item.Errorf("Expecting default value of a variable. Got: %v", item)
  1111  			}
  1112  
  1113  			if varType[len(varType)-1] == '!' {
  1114  				return item.Errorf("Type ending with ! can't have default value: Got: %v", varType)
  1115  			}
  1116  
  1117  			// If value is empty replace, otherwise ignore the default value
  1118  			// as the intialised value will override the default value.
  1119  			if vmap[varName].Value == "" {
  1120  				uq, err := unquoteIfQuoted(it.Val)
  1121  				if err != nil {
  1122  					return err
  1123  				}
  1124  				vmap[varName] = varInfo{
  1125  					Value: uq,
  1126  					Type:  varType,
  1127  				}
  1128  			}
  1129  		} else if item.Typ == itemRightRound {
  1130  			break
  1131  		} else {
  1132  			// We consumed an extra item to see if it was an '=' sign, so move back.
  1133  			it.Prev()
  1134  		}
  1135  		expectArg = false
  1136  	}
  1137  	return nil
  1138  }
  1139  
  1140  // unquoteIfQuoted checks if str is quoted (starts and ends with quotes). If
  1141  // so, it tries to unquote str possibly returning an error. Otherwise, the
  1142  // original value is returned.
  1143  func unquoteIfQuoted(str string) (string, error) {
  1144  	if len(str) < 2 || str[0] != quote || str[len(str)-1] != quote {
  1145  		return str, nil
  1146  	}
  1147  	uq, err := strconv.Unquote(str)
  1148  	return uq, errors.Wrapf(err, "could not unquote %q:", str)
  1149  }
  1150  
  1151  // parseArguments parses the arguments part of the GraphQL query root.
  1152  func parseArguments(it *lex.ItemIterator, gq *GraphQuery) (result []pair, rerr error) {
  1153  	expectArg := true
  1154  	orderCount := 0
  1155  	for it.Next() {
  1156  		var p pair
  1157  		// Get key.
  1158  		item := it.Item()
  1159  		if item.Typ == itemName {
  1160  			if !expectArg {
  1161  				return result, item.Errorf("Expecting a comma. But got: %v", item.Val)
  1162  			}
  1163  			p.Key = collectName(it, item.Val)
  1164  			if isSortkey(p.Key) {
  1165  				orderCount++
  1166  			}
  1167  			expectArg = false
  1168  		} else if item.Typ == itemRightRound {
  1169  			if expectArg {
  1170  				return result, item.Errorf("Expected argument but got ')'.")
  1171  			}
  1172  			break
  1173  		} else if item.Typ == itemComma {
  1174  			if expectArg {
  1175  				return result, item.Errorf("Expected Argument but got comma.")
  1176  			}
  1177  			expectArg = true
  1178  			continue
  1179  		} else {
  1180  			return result, item.Errorf("Expecting argument name. Got: %v", item)
  1181  		}
  1182  
  1183  		it.Next()
  1184  		item = it.Item()
  1185  		if item.Typ != itemColon {
  1186  			return result, item.Errorf("Expecting a colon. Got: %v in %v", item, gq.Attr)
  1187  		}
  1188  
  1189  		// Get value.
  1190  		it.Next()
  1191  		item = it.Item()
  1192  		var val string
  1193  		if item.Val == valueFunc {
  1194  			count, err := parseVarList(it, gq)
  1195  			if err != nil {
  1196  				return result, err
  1197  			}
  1198  			if count != 1 {
  1199  				return result, item.Errorf("Only one variable expected. Got %d", count)
  1200  			}
  1201  			gq.NeedsVar[len(gq.NeedsVar)-1].Typ = ValueVar
  1202  			p.Val = gq.NeedsVar[len(gq.NeedsVar)-1].Name
  1203  			result = append(result, p)
  1204  			if isSortkey(p.Key) && orderCount > 1 {
  1205  				return result, item.Errorf("Multiple sorting only allowed by predicates. Got: %+v",
  1206  					p.Val)
  1207  			}
  1208  			continue
  1209  		}
  1210  
  1211  		if item.Typ == itemDollar {
  1212  			val = "$"
  1213  			it.Next()
  1214  			item = it.Item()
  1215  			if item.Typ != itemName {
  1216  				return result, item.Errorf("Expecting argument value. Got: %v", item)
  1217  			}
  1218  		} else if item.Typ == itemMathOp {
  1219  			if item.Val != "+" && item.Val != "-" {
  1220  				return result, item.Errorf("Only Plus and minus are allowed unary ops. Got: %v",
  1221  					item.Val)
  1222  			}
  1223  			val = item.Val
  1224  			it.Next()
  1225  			item = it.Item()
  1226  		} else if item.Typ != itemName {
  1227  			return result, item.Errorf("Expecting argument value. Got: %v", item)
  1228  		}
  1229  
  1230  		p.Val = collectName(it, val+item.Val)
  1231  
  1232  		// Get language list, if present
  1233  		items, err := it.Peek(1)
  1234  		if err == nil && items[0].Typ == itemAt {
  1235  			it.Next() // consume '@'
  1236  			it.Next() // move forward
  1237  			langs, err := parseLanguageList(it)
  1238  			if err != nil {
  1239  				return nil, err
  1240  			}
  1241  			p.Val = p.Val + "@" + strings.Join(langs, ":")
  1242  		}
  1243  
  1244  		result = append(result, p)
  1245  	}
  1246  	return result, nil
  1247  }
  1248  
  1249  // debugString converts FilterTree to a string. Good for testing, debugging.
  1250  // nolint: unused
  1251  func (f *FilterTree) debugString() string {
  1252  	buf := bytes.NewBuffer(make([]byte, 0, 20))
  1253  	f.stringHelper(buf)
  1254  	return buf.String()
  1255  }
  1256  
  1257  // stringHelper does simple DFS to convert FilterTree to string.
  1258  // nolint: unused
  1259  func (f *FilterTree) stringHelper(buf *bytes.Buffer) {
  1260  	x.AssertTrue(f != nil)
  1261  	if f.Func != nil && len(f.Func.Name) > 0 {
  1262  		// Leaf node.
  1263  		buf.WriteRune('(')
  1264  		buf.WriteString(f.Func.Name)
  1265  
  1266  		if len(f.Func.Attr) > 0 {
  1267  			buf.WriteRune(' ')
  1268  			if f.Func.IsCount {
  1269  				buf.WriteString("count(")
  1270  			} else if f.Func.IsValueVar {
  1271  				buf.WriteString("val(")
  1272  			} else if f.Func.IsLenVar {
  1273  				buf.WriteString("len(")
  1274  			}
  1275  			buf.WriteString(f.Func.Attr)
  1276  			if f.Func.IsCount || f.Func.IsValueVar || f.Func.IsLenVar {
  1277  				buf.WriteRune(')')
  1278  			}
  1279  			if len(f.Func.Lang) > 0 {
  1280  				buf.WriteRune('@')
  1281  				buf.WriteString(f.Func.Lang)
  1282  			}
  1283  
  1284  			for _, arg := range f.Func.Args {
  1285  				if arg.IsValueVar {
  1286  					buf.WriteString(" val(")
  1287  				} else {
  1288  					buf.WriteString(" \"")
  1289  				}
  1290  				buf.WriteString(arg.Value)
  1291  				if arg.IsValueVar {
  1292  					buf.WriteRune(')')
  1293  				} else {
  1294  					buf.WriteRune('"')
  1295  				}
  1296  			}
  1297  		}
  1298  		buf.WriteRune(')')
  1299  		return
  1300  	}
  1301  	// Non-leaf node.
  1302  	buf.WriteRune('(')
  1303  	switch f.Op {
  1304  	case "and":
  1305  		buf.WriteString("AND")
  1306  	case "or":
  1307  		buf.WriteString("OR")
  1308  	case "not":
  1309  		buf.WriteString("NOT")
  1310  	default:
  1311  		x.Fatalf("Unknown operator: %q", f.Op)
  1312  	}
  1313  
  1314  	for _, c := range f.Child {
  1315  		buf.WriteRune(' ')
  1316  		c.stringHelper(buf)
  1317  	}
  1318  	buf.WriteRune(')')
  1319  }
  1320  
  1321  type filterTreeStack struct{ a []*FilterTree }
  1322  
  1323  func (s *filterTreeStack) empty() bool        { return len(s.a) == 0 }
  1324  func (s *filterTreeStack) size() int          { return len(s.a) }
  1325  func (s *filterTreeStack) push(t *FilterTree) { s.a = append(s.a, t) }
  1326  
  1327  func (s *filterTreeStack) popAssert() *FilterTree {
  1328  	x.AssertTrue(!s.empty())
  1329  	last := s.a[len(s.a)-1]
  1330  	s.a = s.a[:len(s.a)-1]
  1331  	return last
  1332  }
  1333  
  1334  func (s *filterTreeStack) pop() (*FilterTree, error) {
  1335  	if s.empty() {
  1336  		return nil, errors.Errorf("Empty stack")
  1337  	}
  1338  	last := s.a[len(s.a)-1]
  1339  	s.a = s.a[:len(s.a)-1]
  1340  	return last, nil
  1341  }
  1342  
  1343  func (s *filterTreeStack) peek() *FilterTree {
  1344  	x.AssertTruef(!s.empty(), "Trying to peek empty stack")
  1345  	return s.a[len(s.a)-1]
  1346  }
  1347  
  1348  func evalStack(opStack, valueStack *filterTreeStack) error {
  1349  	topOp, err := opStack.pop()
  1350  	if err != nil {
  1351  		return errors.Errorf("Invalid filter statement")
  1352  	}
  1353  	if topOp.Op == "not" {
  1354  		// Since "not" is a unary operator, just pop one value.
  1355  		topVal, err := valueStack.pop()
  1356  		if err != nil {
  1357  			return errors.Errorf("Invalid filter statement")
  1358  		}
  1359  		topOp.Child = []*FilterTree{topVal}
  1360  	} else {
  1361  		// "and" and "or" are binary operators, so pop two values.
  1362  		if valueStack.size() < 2 {
  1363  			return errors.Errorf("Invalid filter statement")
  1364  		}
  1365  		topVal1 := valueStack.popAssert()
  1366  		topVal2 := valueStack.popAssert()
  1367  		topOp.Child = []*FilterTree{topVal2, topVal1}
  1368  	}
  1369  	// Push the new value (tree) into the valueStack.
  1370  	valueStack.push(topOp)
  1371  	return nil
  1372  }
  1373  
  1374  func parseGeoArgs(it *lex.ItemIterator, g *Function) error {
  1375  	buf := new(bytes.Buffer)
  1376  	buf.WriteString("[")
  1377  	depth := 1
  1378  	for {
  1379  		if valid := it.Next(); !valid {
  1380  			return it.Errorf("Got EOF while parsing Geo tokens")
  1381  		}
  1382  		item := it.Item()
  1383  		switch item.Typ {
  1384  		case itemLeftSquare:
  1385  			buf.WriteString(item.Val)
  1386  			depth++
  1387  		case itemRightSquare:
  1388  			buf.WriteString(item.Val)
  1389  			depth--
  1390  		case itemMathOp, itemComma, itemName:
  1391  			// Writing tokens to buffer.
  1392  			buf.WriteString(item.Val)
  1393  		default:
  1394  			return item.Errorf("Found invalid item: %s while parsing geo arguments.",
  1395  				item.Val)
  1396  		}
  1397  
  1398  		if depth > 4 || depth < 0 {
  1399  			return item.Errorf("Invalid bracket sequence")
  1400  		} else if depth == 0 {
  1401  			break
  1402  		}
  1403  	}
  1404  	// Lets append the concatenated Geo token to Args.
  1405  	// TODO - See if we can directly encode to Geo format.
  1406  	g.Args = append(g.Args, Arg{Value: buf.String()})
  1407  	items, err := it.Peek(1)
  1408  	if err != nil {
  1409  		return it.Errorf("Unexpected EOF while parsing args")
  1410  	}
  1411  	item := items[0]
  1412  	if item.Typ != itemRightRound && item.Typ != itemComma {
  1413  		return item.Errorf("Expected right round or comma. Got: %+v",
  1414  			items[0])
  1415  	}
  1416  	return nil
  1417  }
  1418  
  1419  // parseIneqArgs will try to parse the arguments inside an array ([]). If the values
  1420  // are prefixed with $ they are treated as Gql variables, otherwise they are used as scalar values.
  1421  // Returns nil on success while appending arguments to the function Args slice. Otherwise
  1422  // returns an error, which can be a parsing or value error.
  1423  func parseIneqArgs(it *lex.ItemIterator, g *Function) error {
  1424  	var expectArg, isDollar bool
  1425  
  1426  	expectArg = true
  1427  	for it.Next() {
  1428  		item := it.Item()
  1429  		switch item.Typ {
  1430  		case itemRightSquare:
  1431  			return nil
  1432  		case itemDollar:
  1433  			if !expectArg {
  1434  				return item.Errorf("Missing comma in argument list declaration")
  1435  			}
  1436  			if item, ok := it.PeekOne(); !ok || item.Typ != itemName {
  1437  				return item.Errorf("Expecting a variable name. Got: %v", item)
  1438  			}
  1439  			isDollar = true
  1440  			continue
  1441  		case itemName:
  1442  			// This is not a $variable, just add the value.
  1443  			if !isDollar {
  1444  				val, err := getValueArg(item.Val)
  1445  				if err != nil {
  1446  					return err
  1447  				}
  1448  				g.Args = append(g.Args, Arg{Value: val})
  1449  				break
  1450  			}
  1451  			// This is a $variable that must be expanded later.
  1452  			val := "$" + item.Val
  1453  			g.Args = append(g.Args, Arg{Value: val, IsGraphQLVar: true})
  1454  		case itemComma:
  1455  			if expectArg {
  1456  				return item.Errorf("Invalid comma in argument list")
  1457  			}
  1458  			expectArg = true
  1459  			continue
  1460  		default:
  1461  			return item.Errorf("Invalid arg list")
  1462  		}
  1463  		expectArg = false
  1464  		isDollar = false
  1465  	}
  1466  	return it.Errorf("Expecting ] to end list but got %v instead", it.Item().Val)
  1467  }
  1468  
  1469  // getValueArg returns a space-trimmed and unquoted version of val.
  1470  // Returns the cleaned string, otherwise empty string and an error.
  1471  func getValueArg(val string) (string, error) {
  1472  	return unquoteIfQuoted(strings.TrimSpace(val))
  1473  }
  1474  
  1475  func validFuncName(name string) bool {
  1476  	if isGeoFunc(name) || isInequalityFn(name) {
  1477  		return true
  1478  	}
  1479  
  1480  	switch name {
  1481  	case "regexp", "anyofterms", "allofterms", "alloftext", "anyoftext",
  1482  		"has", "uid", "uid_in", "anyof", "allof", "type", "match":
  1483  		return true
  1484  	}
  1485  	return false
  1486  }
  1487  
  1488  type regexArgs struct {
  1489  	expr  string
  1490  	flags string
  1491  }
  1492  
  1493  func parseRegexArgs(val string) (regexArgs, error) {
  1494  	end := strings.LastIndex(val, "/")
  1495  	if end < 0 {
  1496  		return regexArgs{}, errors.Errorf("Unexpected error while parsing regex arg: %s", val)
  1497  	}
  1498  	expr := strings.Replace(val[1:end], "\\/", "/", -1)
  1499  	flags := ""
  1500  	if end+1 < len(val) {
  1501  		flags = val[end+1:]
  1502  	}
  1503  
  1504  	return regexArgs{expr, flags}, nil
  1505  }
  1506  
  1507  func parseFunction(it *lex.ItemIterator, gq *GraphQuery) (*Function, error) {
  1508  	function := &Function{}
  1509  	var expectArg, seenFuncArg, expectLang, isDollar bool
  1510  L:
  1511  	for it.Next() {
  1512  		item := it.Item()
  1513  		if item.Typ != itemName {
  1514  			return nil, item.Errorf("Expected a function but got %q", item.Val)
  1515  
  1516  		}
  1517  
  1518  		name := collectName(it, item.Val)
  1519  		function.Name = strings.ToLower(name)
  1520  		if _, ok := tryParseItemType(it, itemLeftRound); !ok {
  1521  			return nil, it.Errorf("Expected ( after func name [%s]", function.Name)
  1522  		}
  1523  
  1524  		attrItemsAgo := -1
  1525  		expectArg = true
  1526  		for it.Next() {
  1527  			itemInFunc := it.Item()
  1528  			if attrItemsAgo >= 0 {
  1529  				attrItemsAgo++
  1530  			}
  1531  			var val string
  1532  			if itemInFunc.Typ == itemRightRound {
  1533  				break L
  1534  			} else if itemInFunc.Typ == itemComma {
  1535  				if expectArg {
  1536  					return nil, itemInFunc.Errorf("Invalid use of comma.")
  1537  				}
  1538  				if isDollar {
  1539  					return nil, itemInFunc.Errorf("Invalid use of comma after dollar.")
  1540  				}
  1541  				expectArg = true
  1542  				continue
  1543  			} else if itemInFunc.Typ == itemLeftRound {
  1544  				// Function inside a function.
  1545  				if seenFuncArg {
  1546  					return nil, itemInFunc.Errorf("Multiple functions as arguments not allowed")
  1547  				}
  1548  				it.Prev()
  1549  				it.Prev()
  1550  				nestedFunc, err := parseFunction(it, gq)
  1551  				if err != nil {
  1552  					return nil, err
  1553  				}
  1554  				seenFuncArg = true
  1555  				if nestedFunc.Name == valueFunc {
  1556  					if len(nestedFunc.NeedsVar) > 1 {
  1557  						return nil, itemInFunc.Errorf("Multiple variables not allowed in a function")
  1558  					}
  1559  					// Variable is used in place of attribute, eq(val(a), 5)
  1560  					if len(function.Attr) == 0 {
  1561  						function.Attr = nestedFunc.NeedsVar[0].Name
  1562  						function.IsValueVar = true
  1563  					} else {
  1564  						// eq(name, val(a))
  1565  						function.Args = append(function.Args,
  1566  							Arg{Value: nestedFunc.NeedsVar[0].Name, IsValueVar: true})
  1567  					}
  1568  					function.NeedsVar = append(function.NeedsVar, nestedFunc.NeedsVar...)
  1569  					function.NeedsVar[0].Typ = ValueVar
  1570  				} else if nestedFunc.Name == lenFunc {
  1571  					if len(nestedFunc.NeedsVar) > 1 {
  1572  						return nil,
  1573  							itemInFunc.Errorf("Multiple variables not allowed in len function")
  1574  					}
  1575  					if !isInequalityFn(function.Name) {
  1576  						return nil,
  1577  							itemInFunc.Errorf("len function only allowed inside inequality" +
  1578  								" function")
  1579  					}
  1580  					function.Attr = nestedFunc.NeedsVar[0].Name
  1581  					function.IsLenVar = true
  1582  					function.NeedsVar = append(function.NeedsVar, nestedFunc.NeedsVar...)
  1583  				} else if nestedFunc.Name == countFunc {
  1584  					function.Attr = nestedFunc.Attr
  1585  					function.IsCount = true
  1586  				} else {
  1587  					return nil, itemInFunc.Errorf("Only val/count/len allowed as function "+
  1588  						"within another. Got: %s", nestedFunc.Name)
  1589  				}
  1590  				expectArg = false
  1591  				continue
  1592  			} else if itemInFunc.Typ == itemAt {
  1593  				if attrItemsAgo != 1 {
  1594  					return nil, itemInFunc.Errorf("Invalid usage of '@' in function " +
  1595  						"argument, must only appear immediately after attr.")
  1596  				}
  1597  				expectLang = true
  1598  				continue
  1599  			} else if itemInFunc.Typ == itemMathOp {
  1600  				val = itemInFunc.Val
  1601  				it.Next()
  1602  				itemInFunc = it.Item()
  1603  			} else if itemInFunc.Typ == itemDollar {
  1604  				if isDollar {
  1605  					return nil, itemInFunc.Errorf("Invalid use of $ in func args")
  1606  				}
  1607  				isDollar = true
  1608  				continue
  1609  			} else if itemInFunc.Typ == itemRegex {
  1610  				ra, err := parseRegexArgs(itemInFunc.Val)
  1611  				if err != nil {
  1612  					return nil, err
  1613  				}
  1614  				function.Args = append(function.Args, Arg{Value: ra.expr}, Arg{Value: ra.flags})
  1615  				expectArg = false
  1616  				continue
  1617  				// Lets reassemble the geo tokens.
  1618  			} else if itemInFunc.Typ == itemLeftSquare {
  1619  				var err error
  1620  				switch {
  1621  				case isGeoFunc(function.Name):
  1622  					err = parseGeoArgs(it, function)
  1623  
  1624  				case isInequalityFn(function.Name):
  1625  					err = parseIneqArgs(it, function)
  1626  
  1627  				default:
  1628  					err = itemInFunc.Errorf("Unexpected character [ while parsing request.")
  1629  				}
  1630  				if err != nil {
  1631  					return nil, err
  1632  				}
  1633  				expectArg = false
  1634  				continue
  1635  			} else if itemInFunc.Typ == itemRightSquare {
  1636  				if _, err := it.Peek(1); err != nil {
  1637  					return nil,
  1638  						itemInFunc.Errorf("Unexpected EOF while parsing args")
  1639  				}
  1640  				expectArg = false
  1641  				continue
  1642  			} else if itemInFunc.Typ != itemName {
  1643  				return nil, itemInFunc.Errorf("Expected arg after func [%s], but got item %v",
  1644  					function.Name, itemInFunc)
  1645  			}
  1646  
  1647  			item, ok := it.PeekOne()
  1648  			if !ok {
  1649  				return nil, item.Errorf("Unexpected item: %v", item)
  1650  			}
  1651  			// Part of function continue
  1652  			if item.Typ == itemLeftRound {
  1653  				continue
  1654  			}
  1655  
  1656  			if !expectArg && !expectLang {
  1657  				return nil, itemInFunc.Errorf("Expected comma or language but got: %s",
  1658  					itemInFunc.Val)
  1659  			}
  1660  
  1661  			vname := collectName(it, itemInFunc.Val)
  1662  			// TODO - Move this to a function.
  1663  			v := strings.Trim(vname, " \t")
  1664  			var err error
  1665  			v, err = unquoteIfQuoted(v)
  1666  			if err != nil {
  1667  				return nil, err
  1668  			}
  1669  			val += v
  1670  
  1671  			if isDollar {
  1672  				val = "$" + val
  1673  				isDollar = false
  1674  				if function.Name == uidFunc && gq != nil {
  1675  					if len(gq.Args["id"]) > 0 {
  1676  						return nil, itemInFunc.Errorf("Only one GraphQL variable " +
  1677  							"allowed inside uid function.")
  1678  					}
  1679  					gq.Args["id"] = val
  1680  				} else {
  1681  					function.Args = append(function.Args, Arg{Value: val, IsGraphQLVar: true})
  1682  				}
  1683  				expectArg = false
  1684  				continue
  1685  			}
  1686  
  1687  			// Unlike other functions, uid function has no attribute, everything is args.
  1688  			if len(function.Attr) == 0 && function.Name != uidFunc &&
  1689  				function.Name != typFunc {
  1690  
  1691  				if strings.ContainsRune(itemInFunc.Val, '"') {
  1692  					return nil, itemInFunc.Errorf("Attribute in function"+
  1693  						" must not be quoted with \": %s", itemInFunc.Val)
  1694  				}
  1695  				function.Attr = val
  1696  				attrItemsAgo = 0
  1697  			} else if expectLang {
  1698  				if val == "*" {
  1699  					return nil, errors.Errorf(
  1700  						"The * symbol cannot be used as a valid language inside functions")
  1701  				}
  1702  				function.Lang = val
  1703  				expectLang = false
  1704  			} else if function.Name != uidFunc {
  1705  				// For UID function. we set g.UID
  1706  				function.Args = append(function.Args, Arg{Value: val})
  1707  			}
  1708  
  1709  			if function.Name == "var" {
  1710  				return nil, itemInFunc.Errorf("Unexpected var(). Maybe you want to try using uid()")
  1711  			}
  1712  
  1713  			expectArg = false
  1714  			if function.Name == valueFunc {
  1715  				// E.g. @filter(gt(val(a), 10))
  1716  				function.NeedsVar = append(function.NeedsVar, VarContext{
  1717  					Name: val,
  1718  					Typ:  ValueVar,
  1719  				})
  1720  			} else if function.Name == lenFunc {
  1721  				// E.g. @filter(gt(len(a), 10))
  1722  				// TODO(Aman): type could be ValueVar too!
  1723  				function.NeedsVar = append(function.NeedsVar, VarContext{
  1724  					Name: val,
  1725  					Typ:  UidVar,
  1726  				})
  1727  			} else if function.Name == uidFunc {
  1728  				// uid function could take variables as well as actual uids.
  1729  				// If we can parse the value that means its an uid otherwise a variable.
  1730  				uid, err := strconv.ParseUint(val, 0, 64)
  1731  				switch e := err.(type) {
  1732  				case nil:
  1733  					// It could be uid function at root.
  1734  					if gq != nil {
  1735  						gq.UID = append(gq.UID, uid)
  1736  						// Or uid function in filter.
  1737  					} else {
  1738  						function.UID = append(function.UID, uid)
  1739  					}
  1740  					continue
  1741  				case *strconv.NumError:
  1742  					if e.Err == strconv.ErrRange {
  1743  						return nil, itemInFunc.Errorf("The uid value %q is too large.", val)
  1744  					}
  1745  				}
  1746  				// E.g. @filter(uid(a, b, c))
  1747  				function.NeedsVar = append(function.NeedsVar, VarContext{
  1748  					Name: val,
  1749  					Typ:  UidVar,
  1750  				})
  1751  			}
  1752  		}
  1753  	}
  1754  
  1755  	if function.Name != uidFunc && function.Name != typFunc && len(function.Attr) == 0 {
  1756  		return nil, it.Errorf("Got empty attr for function: [%s]", function.Name)
  1757  	}
  1758  
  1759  	if function.Name == typFunc && len(function.Args) != 1 {
  1760  		return nil, it.Errorf("type function only supports one argument. Got: %v", function.Args)
  1761  	}
  1762  
  1763  	return function, nil
  1764  }
  1765  
  1766  type facetRes struct {
  1767  	f          *pb.FacetParams
  1768  	ft         *FilterTree
  1769  	vmap       map[string]string
  1770  	facetOrder string
  1771  	orderdesc  bool
  1772  }
  1773  
  1774  func parseFacets(it *lex.ItemIterator) (res facetRes, err error) {
  1775  	res, ok, err := tryParseFacetList(it)
  1776  	if err != nil || ok {
  1777  		return res, err
  1778  	}
  1779  
  1780  	filterTree, err := parseFilter(it)
  1781  	res.ft = filterTree
  1782  	return res, err
  1783  }
  1784  
  1785  type facetItem struct {
  1786  	name      string
  1787  	alias     string
  1788  	varName   string
  1789  	ordered   bool
  1790  	orderdesc bool
  1791  }
  1792  
  1793  // If err != nil, an error happened, abandon parsing.  If err == nil && parseOk == false, the
  1794  // attempt to parse failed, no data was consumed, and there might be a valid alternate parse with a
  1795  // different function.
  1796  func tryParseFacetItem(it *lex.ItemIterator) (res facetItem, parseOk bool, err error) {
  1797  	// We parse this:
  1798  	// [{orderdesc|orderasc|alias}:] [varname as] name
  1799  
  1800  	savePos := it.Save()
  1801  	defer func() {
  1802  		if err == nil && !parseOk {
  1803  			it.Restore(savePos)
  1804  		}
  1805  	}()
  1806  
  1807  	item, ok := tryParseItemType(it, itemName)
  1808  	if !ok {
  1809  		return res, false, nil
  1810  	}
  1811  
  1812  	isOrderasc := item.Val == "orderasc"
  1813  	if _, ok := tryParseItemType(it, itemColon); ok {
  1814  		if isOrderasc || item.Val == "orderdesc" {
  1815  			res.ordered = true
  1816  			res.orderdesc = !isOrderasc
  1817  		} else {
  1818  			res.alias = item.Val
  1819  		}
  1820  
  1821  		// Step past colon.
  1822  		item, ok = tryParseItemType(it, itemName)
  1823  		if !ok {
  1824  			return res, false, item.Errorf("Expected name after colon")
  1825  		}
  1826  	}
  1827  
  1828  	// We've possibly set ordered, orderdesc, alias and now we have consumed another item,
  1829  	// which is a name.
  1830  	name1 := item.Val
  1831  
  1832  	// Now try to consume "as".
  1833  	if !trySkipItemVal(it, "as") {
  1834  		name1 = collectName(it, name1)
  1835  		res.name = name1
  1836  		return res, true, nil
  1837  	}
  1838  	item, ok = tryParseItemType(it, itemName)
  1839  	if !ok {
  1840  		return res, false, item.Errorf("Expected name in facet list")
  1841  	}
  1842  
  1843  	res.name = collectName(it, item.Val)
  1844  	res.varName = name1
  1845  	return res, true, nil
  1846  }
  1847  
  1848  // If err != nil, an error happened, abandon parsing.  If err == nil && parseOk == false, the
  1849  // attempt to parse failed, but there might be a valid alternate parse with a different function,
  1850  // such as parseFilter.
  1851  func tryParseFacetList(it *lex.ItemIterator) (res facetRes, parseOk bool, err error) {
  1852  	savePos := it.Save()
  1853  	defer func() {
  1854  		if err == nil && !parseOk {
  1855  			it.Restore(savePos)
  1856  		}
  1857  	}()
  1858  
  1859  	// Skip past '('
  1860  	if _, ok := tryParseItemType(it, itemLeftRound); !ok {
  1861  		it.Restore(savePos)
  1862  		var facets pb.FacetParams
  1863  		facets.AllKeys = true
  1864  		res.f = &facets
  1865  		res.vmap = make(map[string]string)
  1866  		return res, true, nil
  1867  	}
  1868  
  1869  	facetVar := make(map[string]string)
  1870  	var facets pb.FacetParams
  1871  	var orderdesc bool
  1872  	var orderkey string
  1873  
  1874  	if _, ok := tryParseItemType(it, itemRightRound); ok {
  1875  		// @facets() just parses to an empty set of facets.
  1876  		res.f, res.vmap, res.facetOrder, res.orderdesc = &facets, facetVar, orderkey, orderdesc
  1877  		return res, true, nil
  1878  	}
  1879  
  1880  	for {
  1881  		// We've just consumed a leftRound or a comma.
  1882  
  1883  		// Parse a facet item.
  1884  		// copy the iterator first to facetItemIt so that it corresponds to the parsed facetItem
  1885  		// facetItemIt is used later for reporting errors with line and column numbers
  1886  		facetItemIt := it
  1887  		facetItem, ok, err := tryParseFacetItem(it)
  1888  		if !ok || err != nil {
  1889  			return res, ok, err
  1890  		}
  1891  
  1892  		// Combine the facetitem with our result.
  1893  		{
  1894  			if facetItem.varName != "" {
  1895  				if _, has := facetVar[facetItem.name]; has {
  1896  					return res, false, facetItemIt.Errorf("Duplicate variable mappings for facet %v",
  1897  						facetItem.name)
  1898  				}
  1899  				facetVar[facetItem.name] = facetItem.varName
  1900  			}
  1901  			facets.Param = append(facets.Param, &pb.FacetParam{
  1902  				Key:   facetItem.name,
  1903  				Alias: facetItem.alias,
  1904  			})
  1905  			if facetItem.ordered {
  1906  				if orderkey != "" {
  1907  					return res, false,
  1908  						facetItemIt.Errorf("Invalid use of orderasc/orderdesc in facets")
  1909  				}
  1910  				orderdesc = facetItem.orderdesc
  1911  				orderkey = facetItem.name
  1912  			}
  1913  		}
  1914  
  1915  		// Now what?  Either close-paren or a comma.
  1916  		if _, ok := tryParseItemType(it, itemRightRound); ok {
  1917  			sort.Slice(facets.Param, func(i, j int) bool {
  1918  				return facets.Param[i].Key < facets.Param[j].Key
  1919  			})
  1920  			// deduplicate facets
  1921  			out := facets.Param[:0]
  1922  			flen := len(facets.Param)
  1923  			for i := 1; i < flen; i++ {
  1924  				if facets.Param[i-1].Key == facets.Param[i].Key {
  1925  					continue
  1926  				}
  1927  				out = append(out, facets.Param[i-1])
  1928  			}
  1929  			out = append(out, facets.Param[flen-1])
  1930  			facets.Param = out
  1931  			res.f, res.vmap, res.facetOrder, res.orderdesc = &facets, facetVar, orderkey, orderdesc
  1932  			return res, true, nil
  1933  		}
  1934  		if item, ok := tryParseItemType(it, itemComma); !ok {
  1935  			if len(facets.Param) < 2 {
  1936  				// We have only consumed ``'@facets' '(' <facetItem>`, which means parseFilter might
  1937  				// succeed. Return no-parse, no-error.
  1938  				return res, false, nil
  1939  			}
  1940  			// We've consumed `'@facets' '(' <facetItem> ',' <facetItem>`, so this is definitely
  1941  			// not a filter.  Return an error.
  1942  			return res, false, item.Errorf(
  1943  				"Expected ',' or ')' in facet list: %s", item.Val)
  1944  		}
  1945  	}
  1946  }
  1947  
  1948  // parseGroupby parses the groupby directive.
  1949  func parseGroupby(it *lex.ItemIterator, gq *GraphQuery) error {
  1950  	count := 0
  1951  	expectArg := true
  1952  	it.Next()
  1953  	item := it.Item()
  1954  	alias := ""
  1955  	if item.Typ != itemLeftRound {
  1956  		return item.Errorf("Expected a left round after groupby")
  1957  	}
  1958  	for it.Next() {
  1959  		item := it.Item()
  1960  		if item.Typ == itemRightRound {
  1961  			break
  1962  		}
  1963  		if item.Typ == itemComma {
  1964  			if expectArg {
  1965  				return item.Errorf("Expected a predicate but got comma")
  1966  			}
  1967  			expectArg = true
  1968  		} else if item.Typ == itemName {
  1969  			if !expectArg {
  1970  				return item.Errorf("Expected a comma or right round but got: %v", item.Val)
  1971  			}
  1972  
  1973  			val := collectName(it, item.Val)
  1974  			peekIt, err := it.Peek(1)
  1975  			if err != nil {
  1976  				return err
  1977  			}
  1978  			if peekIt[0].Typ == itemColon {
  1979  				if alias != "" {
  1980  					return item.Errorf("Expected predicate after %s:", alias)
  1981  				}
  1982  				alias = val
  1983  				it.Next() // Consume the itemColon
  1984  				continue
  1985  			}
  1986  
  1987  			var langs []string
  1988  			items, err := it.Peek(1)
  1989  			if err == nil && items[0].Typ == itemAt {
  1990  				it.Next() // consume '@'
  1991  				it.Next() // move forward
  1992  				langs, err = parseLanguageList(it)
  1993  				if err != nil {
  1994  					return err
  1995  				}
  1996  			}
  1997  			attrLang := GroupByAttr{
  1998  				Attr:  val,
  1999  				Alias: alias,
  2000  				Langs: langs,
  2001  			}
  2002  			alias = ""
  2003  			gq.GroupbyAttrs = append(gq.GroupbyAttrs, attrLang)
  2004  			count++
  2005  			expectArg = false
  2006  		}
  2007  	}
  2008  	if expectArg {
  2009  		// use the initial item to report error line and column numbers
  2010  		return item.Errorf("Unnecessary comma in groupby()")
  2011  	}
  2012  	if count == 0 {
  2013  		return item.Errorf("Expected atleast one attribute in groupby")
  2014  	}
  2015  	return nil
  2016  }
  2017  
  2018  func parseType(it *lex.ItemIterator, gq *GraphQuery) error {
  2019  	it.Next()
  2020  	if it.Item().Typ != itemLeftRound {
  2021  		return it.Item().Errorf("Expected a left round after type")
  2022  	}
  2023  
  2024  	it.Next()
  2025  	if it.Item().Typ != itemName {
  2026  		return it.Item().Errorf("Expected a type name inside type directive")
  2027  	}
  2028  	typeName := it.Item().Val
  2029  
  2030  	it.Next()
  2031  	if it.Item().Typ != itemRightRound {
  2032  		return it.Item().Errorf("Expected ) after the type name in type directive")
  2033  	}
  2034  
  2035  	// For now @type(TypeName) is equivalent of filtering using the type function.
  2036  	// Later the type declarations will be used to ensure that the fields inside
  2037  	// each block correspond to the specified type.
  2038  	gq.Filter = &FilterTree{
  2039  		Func: &Function{
  2040  			Name: "type",
  2041  			Args: []Arg{
  2042  				{
  2043  					Value: typeName,
  2044  				},
  2045  			},
  2046  		},
  2047  	}
  2048  
  2049  	return nil
  2050  }
  2051  
  2052  // parseFilter parses the filter directive to produce a QueryFilter / parse tree.
  2053  func parseFilter(it *lex.ItemIterator) (*FilterTree, error) {
  2054  	it.Next()
  2055  	item := it.Item()
  2056  	if item.Typ != itemLeftRound {
  2057  		return nil, item.Errorf("Expected ( after filter directive")
  2058  	}
  2059  
  2060  	// opStack is used to collect the operators in right order.
  2061  	opStack := new(filterTreeStack)
  2062  	opStack.push(&FilterTree{Op: "("}) // Push ( onto operator stack.
  2063  	// valueStack is used to collect the values.
  2064  	valueStack := new(filterTreeStack)
  2065  
  2066  	for it.Next() {
  2067  		item := it.Item()
  2068  		lval := strings.ToLower(item.Val)
  2069  		if lval == "and" || lval == "or" || lval == "not" { // Handle operators.
  2070  			op := lval
  2071  			opPred := filterOpPrecedence[op]
  2072  			x.AssertTruef(opPred > 0, "Expected opPred > 0: %d", opPred)
  2073  			// Evaluate the stack until we see an operator with strictly lower pred.
  2074  			for !opStack.empty() {
  2075  				topOp := opStack.peek()
  2076  				if filterOpPrecedence[topOp.Op] < opPred {
  2077  					break
  2078  				}
  2079  				err := evalStack(opStack, valueStack)
  2080  				if err != nil {
  2081  					return nil, err
  2082  				}
  2083  			}
  2084  			opStack.push(&FilterTree{Op: op}) // Push current operator.
  2085  		} else if item.Typ == itemName { // Value.
  2086  			it.Prev()
  2087  			f, err := parseFunction(it, nil)
  2088  			if err != nil {
  2089  				return nil, err
  2090  			}
  2091  			leaf := &FilterTree{Func: f}
  2092  			valueStack.push(leaf)
  2093  		} else if item.Typ == itemLeftRound { // Just push to op stack.
  2094  			opStack.push(&FilterTree{Op: "("})
  2095  
  2096  		} else if item.Typ == itemRightRound { // Pop op stack until we see a (.
  2097  			for !opStack.empty() {
  2098  				topOp := opStack.peek()
  2099  				if topOp.Op == "(" {
  2100  					break
  2101  				}
  2102  				err := evalStack(opStack, valueStack)
  2103  				if err != nil {
  2104  					return nil, err
  2105  				}
  2106  			}
  2107  			_, err := opStack.pop() // Pop away the (.
  2108  			if err != nil {
  2109  				return nil, item.Errorf("Invalid filter statement")
  2110  			}
  2111  			if opStack.empty() {
  2112  				// The parentheses are balanced out. Let's break.
  2113  				break
  2114  			}
  2115  		} else {
  2116  			return nil, item.Errorf("Unexpected item while parsing @filter: %v", item)
  2117  		}
  2118  	}
  2119  
  2120  	// For filters, we start with ( and end with ). We expect to break out of loop
  2121  	// when the parentheses balance off, and at that point, opStack should be empty.
  2122  	// For other applications, typically after all items are
  2123  	// consumed, we will run a loop like "while opStack is nonempty, evalStack".
  2124  	// This is not needed here.
  2125  	if !opStack.empty() {
  2126  		return nil, item.Errorf("Unbalanced parentheses in @filter statement")
  2127  	}
  2128  
  2129  	if valueStack.empty() {
  2130  		// This happens when we have @filter(). We can either return an error or
  2131  		// ignore. Currently, let's just ignore and pretend there is no filter.
  2132  		return nil, nil
  2133  	}
  2134  
  2135  	if valueStack.size() != 1 {
  2136  		return nil, item.Errorf("Expected one item in value stack, but got %d",
  2137  			valueStack.size())
  2138  	}
  2139  	return valueStack.pop()
  2140  }
  2141  
  2142  // Parses ID list. Only used for GraphQL variables.
  2143  // TODO - Maybe get rid of this by lexing individual IDs.
  2144  func parseID(val string) ([]uint64, error) {
  2145  	var uids []uint64
  2146  	val = x.WhiteSpace.Replace(val)
  2147  	if val[0] != '[' {
  2148  		uid, err := strconv.ParseUint(val, 0, 64)
  2149  		if err != nil {
  2150  			return nil, err
  2151  		}
  2152  		uids = append(uids, uid)
  2153  		return uids, nil
  2154  	}
  2155  
  2156  	if val[len(val)-1] != ']' {
  2157  		return nil, errors.Errorf("Invalid id list at root. Got: %+v", val)
  2158  	}
  2159  	var buf bytes.Buffer
  2160  	for _, c := range val[1:] {
  2161  		if c == ',' || c == ']' {
  2162  			if buf.Len() == 0 {
  2163  				continue
  2164  			}
  2165  			uid, err := strconv.ParseUint(buf.String(), 0, 64)
  2166  			if err != nil {
  2167  				return nil, err
  2168  			}
  2169  			uids = append(uids, uid)
  2170  			buf.Reset()
  2171  			continue
  2172  		}
  2173  		if c == '[' || c == ')' {
  2174  			return nil, errors.Errorf("Invalid id list at root. Got: %+v", val)
  2175  		}
  2176  		buf.WriteRune(c)
  2177  	}
  2178  	return uids, nil
  2179  }
  2180  
  2181  func parseVarList(it *lex.ItemIterator, gq *GraphQuery) (int, error) {
  2182  	count := 0
  2183  	expectArg := true
  2184  	it.Next()
  2185  	item := it.Item()
  2186  	if item.Typ != itemLeftRound {
  2187  		return count, item.Errorf("Expected a left round after var")
  2188  	}
  2189  	for it.Next() {
  2190  		item := it.Item()
  2191  		if item.Typ == itemRightRound {
  2192  			break
  2193  		}
  2194  		if item.Typ == itemComma {
  2195  			if expectArg {
  2196  				return count, item.Errorf("Expected a variable but got comma")
  2197  			}
  2198  			expectArg = true
  2199  		} else if item.Typ == itemName {
  2200  			if !expectArg {
  2201  				return count, item.Errorf("Expected a variable but got comma")
  2202  			}
  2203  			count++
  2204  			gq.NeedsVar = append(gq.NeedsVar, VarContext{
  2205  				Name: item.Val,
  2206  				Typ:  UidVar,
  2207  			})
  2208  			expectArg = false
  2209  		}
  2210  	}
  2211  	if expectArg {
  2212  		return count, item.Errorf("Unnecessary comma in val()")
  2213  	}
  2214  	return count, nil
  2215  }
  2216  
  2217  func parseDirective(it *lex.ItemIterator, curp *GraphQuery) error {
  2218  	valid := true
  2219  	it.Prev()
  2220  	item := it.Item()
  2221  	if item.Typ == itemLeftCurl {
  2222  		// Ideally we should check that curp was created at current depth.
  2223  		valid = false
  2224  	}
  2225  	it.Next()
  2226  	// No directive is allowed on pb.subgraph like expand all, value variables.
  2227  	if !valid || curp == nil || curp.IsInternal {
  2228  		return item.Errorf("Invalid use of directive.")
  2229  	}
  2230  
  2231  	it.Next()
  2232  	item = it.Item()
  2233  	peek, err := it.Peek(1)
  2234  	if err != nil || item.Typ != itemName {
  2235  		return item.Errorf("Expected directive or language list")
  2236  	}
  2237  
  2238  	if item.Val == "facets" { // because @facets can come w/t '()'
  2239  		res, err := parseFacets(it)
  2240  		if err != nil {
  2241  			return err
  2242  		}
  2243  		if res.f != nil {
  2244  			curp.FacetVar = res.vmap
  2245  			curp.FacetOrder = res.facetOrder
  2246  			curp.FacetDesc = res.orderdesc
  2247  			if curp.Facets != nil {
  2248  				return item.Errorf("Only one facets allowed")
  2249  			}
  2250  			curp.Facets = res.f
  2251  		} else if res.ft != nil {
  2252  			if curp.FacetsFilter != nil {
  2253  				return item.Errorf("Only one facets filter allowed")
  2254  			}
  2255  			if res.ft.hasVars() {
  2256  				return item.Errorf(
  2257  					"variables are not allowed in facets filter.")
  2258  			}
  2259  			curp.FacetsFilter = res.ft
  2260  		} else {
  2261  			return item.Errorf("Facets parsing failed.")
  2262  		}
  2263  	} else if peek[0].Typ == itemLeftRound {
  2264  		// this is directive
  2265  		switch item.Val {
  2266  		case "filter":
  2267  			if curp.Filter != nil {
  2268  				return item.Errorf("Use AND, OR and round brackets instead" +
  2269  					" of multiple filter directives.")
  2270  			}
  2271  			filter, err := parseFilter(it)
  2272  			if err != nil {
  2273  				return err
  2274  			}
  2275  			curp.Filter = filter
  2276  		case "groupby":
  2277  			if curp.IsGroupby {
  2278  				return item.Errorf("Only one group by directive allowed.")
  2279  			}
  2280  			curp.IsGroupby = true
  2281  			if err := parseGroupby(it, curp); err != nil {
  2282  				return err
  2283  			}
  2284  		case "type":
  2285  			err := parseType(it, curp)
  2286  			if err != nil {
  2287  				return err
  2288  			}
  2289  		default:
  2290  			return item.Errorf("Unknown directive [%s]", item.Val)
  2291  		}
  2292  	} else if len(curp.Attr) > 0 && len(curp.Langs) == 0 {
  2293  		// this is language list
  2294  		if curp.Langs, err = parseLanguageList(it); err != nil {
  2295  			return err
  2296  		}
  2297  		if len(curp.Langs) == 0 {
  2298  			return item.Errorf("Expected at least 1 language in list for %s", curp.Attr)
  2299  		}
  2300  	} else {
  2301  		return item.Errorf("Expected directive or language list, got @%s", item.Val)
  2302  	}
  2303  	return nil
  2304  }
  2305  
  2306  func parseLanguageList(it *lex.ItemIterator) ([]string, error) {
  2307  	item := it.Item()
  2308  	var langs []string
  2309  	for ; item.Typ == itemName || item.Typ == itemPeriod; item = it.Item() {
  2310  		langs = append(langs, item.Val)
  2311  		it.Next()
  2312  		if it.Item().Typ == itemColon {
  2313  			it.Next()
  2314  		} else {
  2315  			break
  2316  		}
  2317  	}
  2318  	if it.Item().Typ == itemPeriod {
  2319  		peekIt, err := it.Peek(1)
  2320  		if err != nil {
  2321  			return nil, err
  2322  		}
  2323  		if peekIt[0].Typ == itemPeriod {
  2324  			return nil, it.Errorf("Expected only one dot(.) while parsing language list.")
  2325  		}
  2326  	}
  2327  	it.Prev()
  2328  
  2329  	for _, lang := range langs {
  2330  		if lang == string(star) && len(langs) > 1 {
  2331  			return nil, errors.Errorf(
  2332  				"If * is used, no other languages are allowed in the language list. Found %v",
  2333  				langs)
  2334  		}
  2335  	}
  2336  
  2337  	return langs, nil
  2338  }
  2339  
  2340  func validKeyAtRoot(k string) bool {
  2341  	switch k {
  2342  	case "func", "orderasc", "orderdesc", "first", "offset", "after":
  2343  		return true
  2344  	case "from", "to", "numpaths", "minweight", "maxweight":
  2345  		// Specific to shortest path
  2346  		return true
  2347  	case "depth":
  2348  		return true
  2349  	}
  2350  	return false
  2351  }
  2352  
  2353  // Check for validity of key at non-root nodes.
  2354  func validKey(k string) bool {
  2355  	switch k {
  2356  	case "orderasc", "orderdesc", "first", "offset", "after":
  2357  		return true
  2358  	}
  2359  	return false
  2360  }
  2361  
  2362  func attrAndLang(attrData string) (attr string, langs []string) {
  2363  	idx := strings.Index(attrData, "@")
  2364  	if idx < 0 {
  2365  		return attrData, langs
  2366  	}
  2367  	attr = attrData[:idx]
  2368  	langs = strings.Split(attrData[idx+1:], ":")
  2369  	return
  2370  }
  2371  
  2372  func isEmpty(gq *GraphQuery) bool {
  2373  	return gq.Func == nil && len(gq.NeedsVar) == 0 && len(gq.Args) == 0 &&
  2374  		gq.ShortestPathArgs.From == nil && gq.ShortestPathArgs.To == nil
  2375  }
  2376  
  2377  // getRoot gets the root graph query object after parsing the args.
  2378  func getRoot(it *lex.ItemIterator) (gq *GraphQuery, rerr error) {
  2379  	gq = &GraphQuery{
  2380  		Args: make(map[string]string),
  2381  	}
  2382  	if !it.Next() {
  2383  		return nil, it.Errorf("Invalid query")
  2384  	}
  2385  	item := it.Item()
  2386  	if item.Typ != itemName {
  2387  		return nil, item.Errorf("Expected some name. Got: %v", item)
  2388  	}
  2389  
  2390  	peekIt, err := it.Peek(1)
  2391  	if err != nil {
  2392  		return nil, it.Errorf("Invalid Query")
  2393  	}
  2394  	if peekIt[0].Typ == itemName && strings.ToLower(peekIt[0].Val) == "as" {
  2395  		gq.Var = item.Val
  2396  		it.Next() // Consume the "AS".
  2397  		it.Next()
  2398  		item = it.Item()
  2399  	}
  2400  
  2401  	gq.Alias = item.Val
  2402  	if !it.Next() {
  2403  		return nil, item.Errorf("Invalid query")
  2404  	}
  2405  	item = it.Item()
  2406  	if item.Typ != itemLeftRound {
  2407  		return nil, item.Errorf("Expected Left round brackets. Got: %v", item)
  2408  	}
  2409  
  2410  	expectArg := true
  2411  	order := make(map[string]bool)
  2412  	// Parse in KV fashion. Depending on the value of key, decide the path.
  2413  	for it.Next() {
  2414  		var key string
  2415  		// Get key.
  2416  		item := it.Item()
  2417  		if item.Typ == itemName {
  2418  			if !expectArg {
  2419  				return nil, item.Errorf("Not expecting argument. Got: %v", item)
  2420  			}
  2421  			key = item.Val
  2422  			expectArg = false
  2423  		} else if item.Typ == itemRightRound {
  2424  			if isEmpty(gq) {
  2425  				// Used to do aggregation at root which would be fetched in another block.
  2426  				gq.IsEmpty = true
  2427  			}
  2428  			break
  2429  		} else if item.Typ == itemComma {
  2430  			if expectArg {
  2431  				return nil, item.Errorf("Expected Argument but got comma.")
  2432  			}
  2433  			expectArg = true
  2434  			continue
  2435  		} else {
  2436  			return nil, item.Errorf("Expecting argument name. Got: %v", item)
  2437  		}
  2438  
  2439  		if !validKeyAtRoot(key) {
  2440  			return nil, item.Errorf("Got invalid keyword: %s at root", key)
  2441  		}
  2442  
  2443  		if !it.Next() {
  2444  			return nil, item.Errorf("Invalid query")
  2445  		}
  2446  		item = it.Item()
  2447  		if item.Typ != itemColon {
  2448  			return nil, item.Errorf("Expecting a colon. Got: %v", item)
  2449  		}
  2450  
  2451  		switch key {
  2452  		case "func":
  2453  			// Store the generator function.
  2454  			if gq.Func != nil {
  2455  				return gq, item.Errorf("Only one function allowed at root")
  2456  			}
  2457  			gen, err := parseFunction(it, gq)
  2458  			if err != nil {
  2459  				return gq, err
  2460  			}
  2461  			if !validFuncName(gen.Name) {
  2462  				return nil, item.Errorf("Function name: %s is not valid.", gen.Name)
  2463  			}
  2464  			gq.Func = gen
  2465  			gq.NeedsVar = append(gq.NeedsVar, gen.NeedsVar...)
  2466  		case "from", "to":
  2467  			if gq.Alias != "shortest" {
  2468  				return gq, item.Errorf("from/to only allowed for shortest path queries")
  2469  			}
  2470  
  2471  			fn := &Function{}
  2472  			peekIt, err := it.Peek(1)
  2473  			if err != nil {
  2474  				return nil, item.Errorf("Invalid query")
  2475  			}
  2476  
  2477  			assignShortestPathFn := func(fn *Function, key string) {
  2478  				if key == "from" {
  2479  					gq.ShortestPathArgs.From = fn
  2480  				} else if key == "to" {
  2481  					gq.ShortestPathArgs.To = fn
  2482  				}
  2483  			}
  2484  
  2485  			if peekIt[0].Val == uidFunc {
  2486  				gen, err := parseFunction(it, gq)
  2487  				if err != nil {
  2488  					return gq, err
  2489  				}
  2490  				fn.NeedsVar = gen.NeedsVar
  2491  				fn.Name = gen.Name
  2492  				assignShortestPathFn(fn, key)
  2493  				continue
  2494  			}
  2495  
  2496  			// This means it's not a uid function, so it has to be an actual uid.
  2497  			it.Next()
  2498  			item := it.Item()
  2499  			val := collectName(it, item.Val)
  2500  			uid, err := strconv.ParseUint(val, 0, 64)
  2501  			switch e := err.(type) {
  2502  			case nil:
  2503  				fn.UID = append(fn.UID, uid)
  2504  			case *strconv.NumError:
  2505  				if e.Err == strconv.ErrRange {
  2506  					return nil, item.Errorf("The uid value %q is too large.", val)
  2507  				}
  2508  				return nil,
  2509  					item.Errorf("from/to in shortest path can only accept uid function or an uid."+
  2510  						" Got: %s", val)
  2511  			}
  2512  			assignShortestPathFn(fn, key)
  2513  
  2514  		default:
  2515  			var val string
  2516  			if !it.Next() {
  2517  				return nil, it.Errorf("Invalid query")
  2518  			}
  2519  			item := it.Item()
  2520  
  2521  			if item.Typ == itemDollar {
  2522  				it.Next()
  2523  				item = it.Item()
  2524  				if item.Typ == itemName {
  2525  					val = fmt.Sprintf("$%s", item.Val)
  2526  				} else {
  2527  					return nil, item.Errorf("Expecting a variable name. Got: %v", item)
  2528  				}
  2529  				goto ASSIGN
  2530  			} else if item.Typ == itemMathOp {
  2531  				if item.Val != "+" && item.Val != "-" {
  2532  					return nil,
  2533  						item.Errorf("Only Plus and minus are allowed unary ops. Got: %v",
  2534  							item.Val)
  2535  				}
  2536  				val = item.Val
  2537  				it.Next()
  2538  				item = it.Item()
  2539  			}
  2540  
  2541  			if val == "" && item.Val == valueFunc {
  2542  				count, err := parseVarList(it, gq)
  2543  				if err != nil {
  2544  					return nil, err
  2545  				}
  2546  				if count != 1 {
  2547  					return nil, item.Errorf("Expected only one variable but got: %d", count)
  2548  				}
  2549  				// Modify the NeedsVar context here.
  2550  				gq.NeedsVar[len(gq.NeedsVar)-1].Typ = ValueVar
  2551  			} else {
  2552  				val = collectName(it, val+item.Val)
  2553  				// Get language list, if present
  2554  				items, err := it.Peek(1)
  2555  				if err == nil && items[0].Typ == itemLeftRound {
  2556  					if (key == "orderasc" || key == "orderdesc") && val != valueFunc {
  2557  						return nil, it.Errorf("Expected val(). Got %s() with order.", val)
  2558  					}
  2559  				}
  2560  				if err == nil && items[0].Typ == itemAt {
  2561  					it.Next() // consume '@'
  2562  					it.Next() // move forward
  2563  					langs, err := parseLanguageList(it)
  2564  					if err != nil {
  2565  						return nil, err
  2566  					}
  2567  					val = val + "@" + strings.Join(langs, ":")
  2568  				}
  2569  
  2570  			}
  2571  
  2572  			// TODO - Allow only order by one of variable/predicate for now.
  2573  			if val == "" {
  2574  				// This should only happen in cases like: orderasc: val(c)
  2575  				if len(gq.NeedsVar) == 0 {
  2576  					return nil, it.Errorf("unable to get value when parsing key value pairs")
  2577  				}
  2578  				val = gq.NeedsVar[len(gq.NeedsVar)-1].Name
  2579  				// Right now we only allow one sort by a variable
  2580  				if len(gq.Order) > 0 && isSortkey(key) {
  2581  					return nil, it.Errorf("Multiple sorting only allowed by predicates. "+
  2582  						"Got: %+v", val)
  2583  				}
  2584  			}
  2585  			if isSortkey(key) {
  2586  				if order[val] {
  2587  					return nil, it.Errorf("Sorting by an attribute: [%s] can only be done once", val)
  2588  				}
  2589  				attr, langs := attrAndLang(val)
  2590  				gq.Order = append(gq.Order,
  2591  					&pb.Order{Attr: attr, Desc: key == "orderdesc", Langs: langs})
  2592  				order[val] = true
  2593  				continue
  2594  			}
  2595  
  2596  		ASSIGN:
  2597  			if _, ok := gq.Args[key]; ok {
  2598  				return gq, it.Errorf("Repeated key %q at root", key)
  2599  			}
  2600  			gq.Args[key] = val
  2601  		}
  2602  	}
  2603  
  2604  	return gq, nil
  2605  }
  2606  
  2607  func isSortkey(k string) bool {
  2608  	return k == "orderasc" || k == "orderdesc"
  2609  }
  2610  
  2611  type countType int
  2612  
  2613  const (
  2614  	notSeen      countType = iota // default value
  2615  	seen                          // when we see count keyword
  2616  	seenWithPred                  // when we see a predicate within count.
  2617  )
  2618  
  2619  func validateEmptyBlockItem(it *lex.ItemIterator, val string) error {
  2620  	savePos := it.Save()
  2621  	defer func() {
  2622  		it.Restore(savePos)
  2623  	}()
  2624  
  2625  	fname := val
  2626  	// Could have alias so peek forward to get actual function name.
  2627  	skipped := trySkipItemTyp(it, itemColon)
  2628  	if skipped {
  2629  		item, ok := tryParseItemType(it, itemName)
  2630  		if !ok {
  2631  			return item.Errorf("Expected name. Got: %s", item.Val)
  2632  		}
  2633  		fname = item.Val
  2634  	}
  2635  	ok := trySkipItemTyp(it, itemLeftRound)
  2636  	if !ok || (!isMathBlock(fname) && !isAggregator(fname)) {
  2637  		return it.Errorf("Only aggregation/math functions allowed inside empty blocks."+
  2638  			" Got: %v", fname)
  2639  	}
  2640  	return nil
  2641  }
  2642  
  2643  // godeep constructs the subgraph from the lexed items and a GraphQuery node.
  2644  func godeep(it *lex.ItemIterator, gq *GraphQuery) error {
  2645  	if gq == nil {
  2646  		return it.Errorf("Bad nesting of predicates or functions")
  2647  	}
  2648  	var count countType
  2649  	var alias, varName string
  2650  	curp := gq // Used to track current node, for nesting.
  2651  	for it.Next() {
  2652  		item := it.Item()
  2653  		switch item.Typ {
  2654  		case lex.ItemEOF:
  2655  			return nil
  2656  		case itemRightCurl:
  2657  			return nil
  2658  		case itemPeriod:
  2659  			// looking for ...
  2660  			dots := 1
  2661  			for i := 0; i < 2; i++ {
  2662  				if it.Next() && it.Item().Typ == itemPeriod {
  2663  					dots++
  2664  				}
  2665  			}
  2666  			if dots == 3 {
  2667  				it.Next()
  2668  				item = it.Item()
  2669  				if item.Typ == itemName {
  2670  					// item.Val is expected to start with "..." and to have len >3.
  2671  					gq.Children = append(gq.Children, &GraphQuery{fragment: item.Val})
  2672  					// Unlike itemName, there is no nesting, so do not change "curp".
  2673  				}
  2674  			} else {
  2675  				return item.Errorf("Expected 3 periods (\"...\"), got %d.", dots)
  2676  			}
  2677  		case itemName:
  2678  			peekIt, err := it.Peek(1)
  2679  			if err != nil {
  2680  				return item.Errorf("Invalid query")
  2681  			}
  2682  			if peekIt[0].Typ == itemName && strings.ToLower(peekIt[0].Val) == "as" {
  2683  				varName = item.Val
  2684  				it.Next() // "As" was checked before.
  2685  				continue
  2686  			}
  2687  
  2688  			val := collectName(it, item.Val)
  2689  			valLower := strings.ToLower(val)
  2690  
  2691  			peekIt, err = it.Peek(1)
  2692  			if err != nil {
  2693  				return err
  2694  			}
  2695  			if peekIt[0].Typ == itemColon {
  2696  				alias = val
  2697  				it.Next() // Consume the itemcolon
  2698  				continue
  2699  			}
  2700  
  2701  			if gq.IsGroupby && (!isAggregator(val) && val != "count" && count != seen) {
  2702  				// Only aggregator or count allowed inside the groupby block.
  2703  				return it.Errorf("Only aggregator/count "+
  2704  					"functions allowed inside @groupby. Got: %v", val)
  2705  			}
  2706  
  2707  			if gq.IsEmpty {
  2708  				if err := validateEmptyBlockItem(it, valLower); err != nil {
  2709  					return err
  2710  				}
  2711  			}
  2712  
  2713  			if valLower == "checkpwd" {
  2714  				child := &GraphQuery{
  2715  					Args:  make(map[string]string),
  2716  					Var:   varName,
  2717  					Alias: alias,
  2718  				}
  2719  				varName, alias = "", ""
  2720  				it.Prev()
  2721  				if child.Func, err = parseFunction(it, gq); err != nil {
  2722  					return err
  2723  				}
  2724  				child.Func.Args = append(child.Func.Args, Arg{Value: child.Func.Attr})
  2725  				child.Attr = child.Func.Attr
  2726  				gq.Children = append(gq.Children, child)
  2727  				curp = nil
  2728  				continue
  2729  			} else if isAggregator(valLower) {
  2730  				child := &GraphQuery{
  2731  					Attr:       valueFunc,
  2732  					Args:       make(map[string]string),
  2733  					Var:        varName,
  2734  					IsInternal: true,
  2735  					Alias:      alias,
  2736  				}
  2737  				varName, alias = "", ""
  2738  				it.Next()
  2739  				if it.Item().Typ != itemLeftRound {
  2740  					it.Prev()
  2741  					goto Fall
  2742  				}
  2743  				it.Next()
  2744  				if gq.IsGroupby {
  2745  					item = it.Item()
  2746  					attr := collectName(it, item.Val)
  2747  					// Get language list, if present
  2748  					items, err := it.Peek(1)
  2749  					if err == nil && items[0].Typ == itemAt {
  2750  						it.Next() // consume '@'
  2751  						it.Next() // move forward
  2752  						if child.Langs, err = parseLanguageList(it); err != nil {
  2753  							return err
  2754  						}
  2755  					}
  2756  					child.Attr = attr
  2757  					child.IsInternal = false
  2758  				} else {
  2759  					if it.Item().Val != valueFunc {
  2760  						return it.Errorf("Only variables allowed in aggregate functions. Got: %v",
  2761  							it.Item().Val)
  2762  					}
  2763  					count, err := parseVarList(it, child)
  2764  					if err != nil {
  2765  						return err
  2766  					}
  2767  					if count != 1 {
  2768  						return it.Errorf("Expected one variable inside val() of"+
  2769  							" aggregator but got %v", count)
  2770  					}
  2771  					child.NeedsVar[len(child.NeedsVar)-1].Typ = ValueVar
  2772  				}
  2773  				child.Func = &Function{
  2774  					Name:     valLower,
  2775  					NeedsVar: child.NeedsVar,
  2776  				}
  2777  				it.Next() // Skip the closing ')'
  2778  				gq.Children = append(gq.Children, child)
  2779  				curp = nil
  2780  				continue
  2781  			} else if isMathBlock(valLower) {
  2782  				if varName == "" && alias == "" {
  2783  					return it.Errorf("Function math should be used with a variable or have an alias")
  2784  				}
  2785  				mathTree, again, err := parseMathFunc(it, false)
  2786  				if err != nil {
  2787  					return err
  2788  				}
  2789  				if again {
  2790  					return it.Errorf("Comma encountered in math() at unexpected place.")
  2791  				}
  2792  				child := &GraphQuery{
  2793  					Attr:       val,
  2794  					Alias:      alias,
  2795  					Args:       make(map[string]string),
  2796  					Var:        varName,
  2797  					MathExp:    mathTree,
  2798  					IsInternal: true,
  2799  				}
  2800  				// TODO - See that if we can instead initialize this at the top.
  2801  				varName, alias = "", ""
  2802  				gq.Children = append(gq.Children, child)
  2803  				curp = nil
  2804  				continue
  2805  			} else if isExpandFunc(valLower) {
  2806  				if varName != "" {
  2807  					return it.Errorf("expand() cannot be used with a variable: %s", val)
  2808  				}
  2809  				if alias != "" {
  2810  					return it.Errorf("expand() cannot have an alias")
  2811  				}
  2812  				it.Next() // Consume the '('
  2813  				if it.Item().Typ != itemLeftRound {
  2814  					return it.Errorf("Invalid use of expand()")
  2815  				}
  2816  				it.Next()
  2817  				item := it.Item()
  2818  				child := &GraphQuery{
  2819  					Attr:       val,
  2820  					Args:       make(map[string]string),
  2821  					IsInternal: true,
  2822  				}
  2823  				switch item.Val {
  2824  				case valueFunc:
  2825  					count, err := parseVarList(it, child)
  2826  					if err != nil {
  2827  						return err
  2828  					}
  2829  					if count != 1 {
  2830  						return item.Errorf("Invalid use of expand(). Exactly one variable expected.")
  2831  					}
  2832  					child.NeedsVar[len(child.NeedsVar)-1].Typ = ListVar
  2833  					child.Expand = child.NeedsVar[len(child.NeedsVar)-1].Name
  2834  				case "_all_":
  2835  					child.Expand = "_all_"
  2836  				case "_forward_":
  2837  					child.Expand = "_forward_"
  2838  				case "_reverse_":
  2839  					child.Expand = "_reverse_"
  2840  				default:
  2841  					return item.Errorf("Invalid argument %v in expand()", item.Val)
  2842  				}
  2843  				it.Next() // Consume ')'
  2844  				gq.Children = append(gq.Children, child)
  2845  				// Note: curp is not set to nil. So it can have children, filters, etc.
  2846  				curp = child
  2847  				continue
  2848  			} else if valLower == "count" {
  2849  				if count != notSeen {
  2850  					return it.Errorf("Invalid mention of function count")
  2851  				}
  2852  				count = seen
  2853  				it.Next()
  2854  				item = it.Item()
  2855  				if item.Typ != itemLeftRound {
  2856  					it.Prev()
  2857  					count = notSeen
  2858  					goto Fall
  2859  				}
  2860  
  2861  				peekIt, err := it.Peek(2)
  2862  				if err != nil {
  2863  					return err
  2864  				}
  2865  				if peekIt[0].Typ == itemRightRound {
  2866  					return it.Errorf("Cannot use count(), please use count(uid)")
  2867  				} else if peekIt[0].Val == uidFunc && peekIt[1].Typ == itemRightRound {
  2868  					if gq.IsGroupby {
  2869  						// count(uid) case which occurs inside @groupby
  2870  						val = uidFunc
  2871  						// Skip uid)
  2872  						it.Next()
  2873  						it.Next()
  2874  						goto Fall
  2875  					}
  2876  
  2877  					count = notSeen
  2878  					gq.UidCount = true
  2879  					gq.Var = varName
  2880  					if alias != "" {
  2881  						gq.UidCountAlias = alias
  2882  						// This is a count(uid) node.
  2883  						// Reset the alias here after assigning to UidCountAlias, so that siblings
  2884  						// of this node don't get it.
  2885  						alias = ""
  2886  					}
  2887  					it.Next()
  2888  					it.Next()
  2889  				}
  2890  				continue
  2891  			} else if valLower == valueFunc {
  2892  				if varName != "" {
  2893  					return it.Errorf("Cannot assign a variable to val()")
  2894  				}
  2895  				if count == seen {
  2896  					return it.Errorf("Count of a variable is not allowed")
  2897  				}
  2898  				peekIt, err = it.Peek(1)
  2899  				if err != nil {
  2900  					return err
  2901  				}
  2902  				if peekIt[0].Typ != itemLeftRound {
  2903  					goto Fall
  2904  				}
  2905  
  2906  				child := &GraphQuery{
  2907  					Attr:       val,
  2908  					Args:       make(map[string]string),
  2909  					IsInternal: true,
  2910  					Alias:      alias,
  2911  				}
  2912  				alias = ""
  2913  				count, err := parseVarList(it, child)
  2914  				if err != nil {
  2915  					return err
  2916  				}
  2917  				if count != 1 {
  2918  					return it.Errorf("Invalid use of val(). Exactly one variable expected.")
  2919  				}
  2920  				// Only value vars can be retrieved.
  2921  				child.NeedsVar[len(child.NeedsVar)-1].Typ = ValueVar
  2922  				gq.Children = append(gq.Children, child)
  2923  				curp = nil
  2924  				continue
  2925  			} else if valLower == uidFunc {
  2926  				if count == seen {
  2927  					return it.Errorf("Count of a variable is not allowed")
  2928  				}
  2929  				peekIt, err = it.Peek(1)
  2930  				if err != nil {
  2931  					return err
  2932  				}
  2933  				if peekIt[0].Typ != itemLeftRound {
  2934  					goto Fall
  2935  				}
  2936  				return it.Errorf("Cannot do uid() of a variable")
  2937  			}
  2938  		Fall:
  2939  			if count == seenWithPred {
  2940  				return it.Errorf("Multiple predicates not allowed in single count.")
  2941  			}
  2942  			child := &GraphQuery{
  2943  				Args:    make(map[string]string),
  2944  				Attr:    val,
  2945  				IsCount: count == seen,
  2946  				Var:     varName,
  2947  				Alias:   alias,
  2948  			}
  2949  
  2950  			if gq.IsCount {
  2951  				return it.Errorf("Cannot have children attributes when asking for count.")
  2952  			}
  2953  			gq.Children = append(gq.Children, child)
  2954  			varName, alias = "", ""
  2955  			curp = child
  2956  			if count == seen {
  2957  				count = seenWithPred
  2958  			}
  2959  		case itemLeftCurl:
  2960  			if curp == nil {
  2961  				return it.Errorf("Query syntax invalid.")
  2962  			}
  2963  			if len(curp.Langs) > 0 {
  2964  				return it.Errorf("Cannot have children for attr: %s with lang tags: %v", curp.Attr,
  2965  					curp.Langs)
  2966  			}
  2967  			if err := godeep(it, curp); err != nil {
  2968  				return err
  2969  			}
  2970  		case itemLeftRound:
  2971  			if curp == nil {
  2972  				return it.Errorf("Query syntax invalid.")
  2973  			}
  2974  			if curp.Attr == "" {
  2975  				return it.Errorf("Predicate name cannot be empty.")
  2976  			}
  2977  			args, err := parseArguments(it, curp)
  2978  			if err != nil {
  2979  				return err
  2980  			}
  2981  			// Stores args in GraphQuery, will be used later while retrieving results.
  2982  			order := make(map[string]bool)
  2983  			for _, p := range args {
  2984  				if !validKey(p.Key) {
  2985  					return it.Errorf("Got invalid keyword: %s", p.Key)
  2986  				}
  2987  				if _, ok := curp.Args[p.Key]; ok {
  2988  					return it.Errorf("Got repeated key %q at level %q", p.Key, curp.Attr)
  2989  				}
  2990  				if p.Val == "" {
  2991  					return it.Errorf("Got empty argument")
  2992  				}
  2993  				if p.Key == "orderasc" || p.Key == "orderdesc" {
  2994  					if order[p.Val] {
  2995  						return it.Errorf("Sorting by an attribute: [%s] "+
  2996  							"can only be done once", p.Val)
  2997  					}
  2998  					attr, langs := attrAndLang(p.Val)
  2999  					curp.Order = append(curp.Order,
  3000  						&pb.Order{Attr: attr, Desc: p.Key == "orderdesc", Langs: langs})
  3001  					order[p.Val] = true
  3002  					continue
  3003  				}
  3004  
  3005  				curp.Args[p.Key] = p.Val
  3006  			}
  3007  		case itemAt:
  3008  			err := parseDirective(it, curp)
  3009  			if err != nil {
  3010  				return err
  3011  			}
  3012  
  3013  		case itemRightRound:
  3014  			if count != seenWithPred {
  3015  				return it.Errorf("Invalid mention of brackets")
  3016  			}
  3017  			count = notSeen
  3018  		}
  3019  	}
  3020  	return nil
  3021  }
  3022  
  3023  func isAggregator(fname string) bool {
  3024  	return fname == "min" || fname == "max" || fname == "sum" || fname == "avg"
  3025  }
  3026  
  3027  func isExpandFunc(name string) bool {
  3028  	return name == "expand"
  3029  }
  3030  
  3031  func isMathBlock(name string) bool {
  3032  	return name == "math"
  3033  }
  3034  
  3035  func isGeoFunc(name string) bool {
  3036  	return name == "near" || name == "contains" || name == "within" || name == "intersects"
  3037  }
  3038  
  3039  func isInequalityFn(name string) bool {
  3040  	switch name {
  3041  	case "eq", "le", "ge", "gt", "lt":
  3042  		return true
  3043  	}
  3044  	return false
  3045  }
  3046  
  3047  // Name can have dashes or alphanumeric characters. Lexer lexes them as separate items.
  3048  // We put it back together here.
  3049  func collectName(it *lex.ItemIterator, val string) string {
  3050  	var dashOrName bool // false if expecting dash, true if expecting name
  3051  	for {
  3052  		items, err := it.Peek(1)
  3053  		if err == nil && ((items[0].Typ == itemName && dashOrName) ||
  3054  			(items[0].Val == "-" && !dashOrName)) {
  3055  			it.Next()
  3056  			val += it.Item().Val
  3057  			dashOrName = !dashOrName
  3058  		} else {
  3059  			break
  3060  		}
  3061  	}
  3062  	return val
  3063  }
  3064  
  3065  // Steps the parser.
  3066  func tryParseItemType(it *lex.ItemIterator, typ lex.ItemType) (lex.Item, bool) {
  3067  	item, ok := it.PeekOne()
  3068  	if !ok || item.Typ != typ {
  3069  		return item, false
  3070  	}
  3071  	it.Next()
  3072  	return item, true
  3073  }
  3074  
  3075  func trySkipItemVal(it *lex.ItemIterator, val string) bool {
  3076  	item, ok := it.PeekOne()
  3077  	if !ok || item.Val != val {
  3078  		return false
  3079  	}
  3080  	it.Next()
  3081  	return true
  3082  }
  3083  
  3084  func trySkipItemTyp(it *lex.ItemIterator, typ lex.ItemType) bool {
  3085  	item, ok := it.PeekOne()
  3086  	if !ok || item.Typ != typ {
  3087  		return false
  3088  	}
  3089  	it.Next()
  3090  	return true
  3091  }