github.com/CiscoM31/godata@v1.0.10/parser.go (about)

     1  package godata
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"regexp"
     8  	"sort"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  const (
    14  	OpAssociationLeft int = iota
    15  	OpAssociationRight
    16  	OpAssociationNone
    17  )
    18  
    19  const (
    20  	TokenListExpr = "list"
    21  
    22  	// TokenComma is the default separator for function arguments.
    23  	TokenComma      = ","
    24  	TokenOpenParen  = "("
    25  	TokenCloseParen = ")"
    26  )
    27  
    28  type Tokenizer struct {
    29  	TokenMatchers  []*TokenMatcher
    30  	IgnoreMatchers []*TokenMatcher
    31  }
    32  
    33  type TokenMatcher struct {
    34  	Pattern         string                 // The regular expression matching a ODATA query token, such as literal value, operator or function
    35  	Re              *regexp.Regexp         // The compiled regex
    36  	Token           TokenType              // The token identifier
    37  	CaseInsensitive bool                   // Regex is case-insensitive
    38  	Subst           func(in string) string // A function that substitutes the raw input token with another representation. By default it is the identity.
    39  }
    40  
    41  // TokenType is the interface that must be implemented by all token types.
    42  type TokenType interface {
    43  	Value() int
    44  }
    45  
    46  type ListExprToken int
    47  
    48  func (l ListExprToken) Value() int {
    49  	return (int)(l)
    50  }
    51  
    52  func (l ListExprToken) String() string {
    53  	return [...]string{
    54  		"TokenTypeListExpr",
    55  		"TokenTypeArgCount",
    56  	}[l]
    57  }
    58  
    59  const (
    60  	// TokenTypeListExpr represents a parent node for a variadic listExpr.
    61  	// "list"
    62  	//   "item1"
    63  	//   "item2"
    64  	//   ...
    65  	TokenTypeListExpr ListExprToken = iota
    66  	// TokenTypeArgCount is used to specify the number of arguments of a function or listExpr
    67  	// This is used to handle variadic functions and listExpr.
    68  	TokenTypeArgCount
    69  )
    70  
    71  type Token struct {
    72  	Value string
    73  	Type  TokenType
    74  	// Holds information about the semantic meaning of this token taken from the
    75  	// context of the GoDataService.
    76  	SemanticType      SemanticType
    77  	SemanticReference interface{}
    78  }
    79  
    80  func (t *Tokenizer) Add(pattern string, token TokenType) {
    81  	t.AddWithSubstituteFunc(pattern, token, func(in string) string { return in })
    82  }
    83  
    84  func (t *Tokenizer) AddWithSubstituteFunc(pattern string, token TokenType, subst func(string) string) {
    85  	matcher := createTokenMatcher(pattern, token, subst)
    86  	t.TokenMatchers = append(t.TokenMatchers, matcher)
    87  }
    88  
    89  func createTokenMatcher(pattern string, token TokenType, subst func(string) string) *TokenMatcher {
    90  	rxp := regexp.MustCompile(pattern)
    91  	return &TokenMatcher{
    92  		Pattern:         pattern,
    93  		Re:              rxp,
    94  		Token:           token,
    95  		CaseInsensitive: strings.Contains(pattern, "(?i)"),
    96  		Subst:           subst,
    97  	}
    98  }
    99  
   100  func (t *Tokenizer) Ignore(pattern string, token TokenType) {
   101  	rxp := regexp.MustCompile(pattern)
   102  	matcher := &TokenMatcher{
   103  		Pattern:         pattern,
   104  		Re:              rxp,
   105  		Token:           token,
   106  		CaseInsensitive: strings.Contains(pattern, "(?i)"),
   107  		Subst:           func(in string) string { return in },
   108  	}
   109  	t.IgnoreMatchers = append(t.IgnoreMatchers, matcher)
   110  }
   111  
   112  // TokenizeBytes takes the input byte array and returns an array of tokens.
   113  // Return an empty array if there are no tokens.
   114  func (t *Tokenizer) TokenizeBytes(ctx context.Context, target []byte) ([]*Token, error) {
   115  	result := make([]*Token, 0)
   116  	match := true // false when no match is found
   117  	for len(target) > 0 && match {
   118  		match = false
   119  		ignore := false
   120  		var tokens [][]byte
   121  		var m *TokenMatcher
   122  		for _, m = range t.TokenMatchers {
   123  			tokens = m.Re.FindSubmatch(target)
   124  			if len(tokens) > 0 {
   125  				match = true
   126  				break
   127  			}
   128  		}
   129  		if len(tokens) == 0 {
   130  			for _, m = range t.IgnoreMatchers {
   131  				tokens = m.Re.FindSubmatch(target)
   132  				if len(tokens) > 0 {
   133  					ignore = true
   134  					break
   135  				}
   136  			}
   137  		}
   138  		if len(tokens) > 0 {
   139  			match = true
   140  			var parsed Token
   141  			var token []byte
   142  			// If the regex includes a named group and the name of that group is "token"
   143  			// then the value of the token is set to the subgroup. Other characters are
   144  			// not consumed by the tokenization process.
   145  			// For example, the regex:
   146  			//    ^(?P<token>(eq|ne|gt|ge|lt|le|and|or|not|has|in))\\s
   147  			// has a group named 'token' and the group is followed by a mandatory space character.
   148  			// If the input data is `Name eq 'Bob'`, the token is correctly set to 'eq' and
   149  			// the space after eq is not consumed, because the space character itself is supposed
   150  			// to be the next token.
   151  			//
   152  			// If Token.Value needs to be a sub-regex but the entire token needs to be consumed,
   153  			// use 'subtoken'
   154  			//    ^(duration)?'(?P<subtoken>[0-9])'
   155  			l := 0
   156  			if idx := m.Re.SubexpIndex("token"); idx > 0 {
   157  				token = tokens[idx]
   158  				l = len(token)
   159  			} else if idx := m.Re.SubexpIndex("subtoken"); idx > 0 {
   160  				token = tokens[idx]
   161  				l = len(tokens[0])
   162  			} else {
   163  				token = tokens[0]
   164  				l = len(token)
   165  			}
   166  			target = target[l:] // remove the token from the input
   167  			if !ignore {
   168  				var v string
   169  				if m.CaseInsensitive {
   170  					// In ODATA 4.0.1, operators and functions are case insensitive.
   171  					v = strings.ToLower(string(token))
   172  				} else {
   173  					v = string(token)
   174  				}
   175  				parsed = Token{
   176  					Value: m.Subst(v),
   177  					Type:  m.Token,
   178  				}
   179  				result = append(result, &parsed)
   180  			}
   181  		}
   182  	}
   183  
   184  	if len(target) > 0 && !match {
   185  		return result, BadRequestError(fmt.Sprintf("Token '%s' is invalid", string(target)))
   186  	}
   187  	if len(result) < 1 {
   188  		return result, BadRequestError("Empty query parameter")
   189  	}
   190  	return result, nil
   191  }
   192  
   193  func (t *Tokenizer) Tokenize(ctx context.Context, target string) ([]*Token, error) {
   194  	return t.TokenizeBytes(ctx, []byte(target))
   195  }
   196  
   197  type TokenHandler func(token *Token, stack tokenStack) error
   198  
   199  type Parser struct {
   200  	// Map from string inputs to operator types
   201  	Operators map[string]*Operator
   202  	// Map from string inputs to function types
   203  	Functions map[string]*Function
   204  
   205  	LiteralToken TokenType
   206  }
   207  
   208  type Operator struct {
   209  	Token string
   210  	// Whether the operator is left/right/or not associative.
   211  	// Determines how operators of the same precedence are grouped in the absence of parentheses.
   212  	Association int
   213  	// The number of operands this operator operates on
   214  	Operands int
   215  	// Rank of precedence. A higher value indicates higher precedence.
   216  	Precedence int
   217  	// Determine if the operands should be interpreted as a ListExpr or parenExpr according
   218  	// to ODATA ABNF grammar.
   219  	// This is only used when a listExpr has zero or one items.
   220  	// When a listExpr has 2 or more items, there is no ambiguity between listExpr and parenExpr.
   221  	// For example:
   222  	//    2 + (3) ==> the right operand is a parenExpr.
   223  	//    City IN ('Seattle', 'Atlanta') ==> the right operand is unambiguously a listExpr.
   224  	//    City IN ('Seattle') ==> the right operand should be a listExpr.
   225  	PreferListExpr bool
   226  }
   227  
   228  func (o *Operator) WithListExprPreference(v bool) *Operator {
   229  	o.PreferListExpr = v
   230  	return o
   231  }
   232  
   233  type Function struct {
   234  	Token  string // The function token
   235  	Params []int  // The number of parameters this function accepts
   236  	ReturnsBool bool // Indicates if the function has a boolean return value
   237  }
   238  
   239  type ParseNode struct {
   240  	Token    *Token
   241  	Parent   *ParseNode
   242  	Children []*ParseNode
   243  }
   244  
   245  func (p *ParseNode) String() string {
   246  	var sb strings.Builder
   247  	var treePrinter func(n *ParseNode, sb *strings.Builder, level int, idx *int)
   248  
   249  	treePrinter = func(n *ParseNode, s *strings.Builder, level int, idx *int) {
   250  		if n == nil || n.Token == nil {
   251  			s.WriteRune('\n')
   252  			return
   253  		}
   254  		s.WriteString(fmt.Sprintf("[%2d][%2d]", *idx, n.Token.Type))
   255  		*idx += 1
   256  		s.WriteString(strings.Repeat("  ", level))
   257  		s.WriteString(n.Token.Value)
   258  		s.WriteRune('\n')
   259  		for _, v := range n.Children {
   260  			treePrinter(v, s, level+1, idx)
   261  		}
   262  	}
   263  	idx := 0
   264  	treePrinter(p, &sb, 0, &idx)
   265  	return sb.String()
   266  }
   267  
   268  func EmptyParser() *Parser {
   269  	return &Parser{
   270  		Operators:    make(map[string]*Operator),
   271  		Functions:    make(map[string]*Function),
   272  		LiteralToken: nil,
   273  	}
   274  }
   275  
   276  func (p *Parser) WithLiteralToken(token TokenType) *Parser {
   277  	p.LiteralToken = token
   278  	return p
   279  }
   280  
   281  // DefineOperator adds an operator to the language.
   282  // Provide the token, the expected number of arguments,
   283  // whether the operator is left, right, or not associative, and a precedence.
   284  func (p *Parser) DefineOperator(token string, operands, assoc, precedence int) *Operator {
   285  	op := &Operator{
   286  		Token:       token,
   287  		Association: assoc,
   288  		Operands:    operands,
   289  		Precedence:  precedence,
   290  	}
   291  	p.Operators[token] = op
   292  	return op
   293  }
   294  
   295  // DefineFunction adds a function to the language.
   296  // - params is the number of parameters this function accepts
   297  // - returnsBool indicates if the function has a boolean return value
   298  func (p *Parser) DefineFunction(token string, params []int, returnsBool bool) *Function {
   299  	sort.Sort(sort.Reverse(sort.IntSlice(params)))
   300  	f := &Function{token, params, returnsBool}
   301  	p.Functions[token] = f
   302  	return f
   303  }
   304  
   305  // CustomFunctionInput serves as input to function DefineCustomFunctions()
   306  type CustomFunctionInput struct {
   307  	Name      string // case-insensitive function name
   308  	NumParams []int  // number of allowed parameters
   309  	ReturnsBool bool // indicates if the function has a boolean return value
   310  }
   311  
   312  // DefineCustomFunctions introduces additional function names to be considered as legal function
   313  // names while parsing. The function names must be different from all canonical functions and
   314  // operators defined in the odata specification.
   315  //
   316  // See https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_Functions
   317  func DefineCustomFunctions(functions []CustomFunctionInput) error {
   318  	var funcNames []string
   319  	for _, v := range functions {
   320  		name := strings.ToLower(v.Name)
   321  
   322  		if GlobalExpressionParser.Functions[name] != nil {
   323  			return fmt.Errorf("custom function '%s' may not override odata canonical function", name)
   324  		} else if GlobalExpressionParser.Operators[name] != nil {
   325  			return fmt.Errorf("custom function '%s' may not override odata operator", name)
   326  		}
   327  
   328  		GlobalExpressionParser.DefineFunction(name, v.NumParams, v.ReturnsBool)
   329  		funcNames = append(funcNames, name)
   330  	}
   331  
   332  	// create a regex that performs a case-insensitive match of any one of the provided function names
   333  	pattern := fmt.Sprintf("(?i)^(?P<token>(%s))[\\s(]", strings.Join(funcNames, "|"))
   334  	matcher := createTokenMatcher(pattern, ExpressionTokenFunc, func(in string) string { return in })
   335  
   336  	// The tokenizer has a list of matcher expressions which are evaluated in order while parsing
   337  	// with the first matching rule being applied. The matcher for custom functions is inserted
   338  	// immediately following the matcher for functions defined in the Odata specification (identified
   339  	// by finding rule with type ExpressionTokenFunc). Because the rules are applied in order based
   340  	// on specificity, inserting at this location ensures the custom function rule has similar
   341  	// precedence as functioned defined the Odata specification.
   342  	list := GlobalExpressionTokenizer.TokenMatchers
   343  	for i, v := range GlobalExpressionTokenizer.TokenMatchers {
   344  		if v.Token == ExpressionTokenFunc {
   345  			list = append(list[:i+1], list[i:]...)
   346  			list[i] = matcher
   347  			GlobalExpressionTokenizer.TokenMatchers = list
   348  			return nil
   349  		}
   350  	}
   351  
   352  	// This is a godata package bug. The tokenizer should define matches for the token
   353  	// type ExpressionTokenFunc for functions defined in the Odata specification.
   354  	// Such as substring and tolower.
   355  	return errors.New("godata parser is missing function matchers")
   356  }
   357  
   358  func (p *Parser) isFunction(token *Token) bool {
   359  	_, ok := p.Functions[token.Value]
   360  	return ok
   361  }
   362  
   363  func (p *Parser) isOperator(token *Token) bool {
   364  	_, ok := p.Operators[token.Value]
   365  	return ok
   366  }
   367  
   368  // isBooleanExpression returns True when the expression token 't' has a resulting boolean value
   369  func (p *Parser) isBooleanExpression(t *Token) bool {
   370  	switch t.Type {
   371  	case ExpressionTokenBoolean:
   372  		// Valid boolean expression
   373  	case ExpressionTokenLogical:
   374  		// eq|ne|gt|ge|lt|le|and|or|not|has|in
   375  		// Valid boolean expression
   376  	case ExpressionTokenFunc:
   377  		// Depends on function return type
   378  		f := p.Functions[t.Value]
   379  		if !f.ReturnsBool {
   380  			return false
   381  		}
   382  	case ExpressionTokenLambdaNav:
   383  		// Lambda Navigation.
   384  		// Valid boolean expression
   385  	default:
   386  		return false
   387  	}
   388  	return true
   389  }
   390  
   391  // InfixToPostfix parses the input string of tokens using the given definitions of operators
   392  // and functions.
   393  // Everything else is assumed to be a literal.
   394  // Uses the Shunting-Yard algorithm.
   395  //
   396  // Infix notation for variadic functions and operators: f ( a, b, c, d )
   397  // Postfix notation with wall notation:                 | a b c d f
   398  // Postfix notation with count notation:                a b c d 4 f
   399  func (p *Parser) InfixToPostfix(ctx context.Context, tokens []*Token) (*tokenQueue, error) {
   400  	queue := tokenQueue{} // output queue in postfix
   401  	stack := tokenStack{} // Operator stack
   402  
   403  	previousTokenIsLiteral := false
   404  	var previousToken *Token = nil
   405  
   406  	incrementListArgCount := func(token *Token) {
   407  		if !stack.Empty() {
   408  			if previousToken != nil && previousToken.Value == TokenOpenParen {
   409  				stack.Head.listArgCount++
   410  			} else if stack.Head.Token.Value == TokenOpenParen {
   411  				stack.Head.listArgCount++
   412  			}
   413  		}
   414  	}
   415  	cfg, hasComplianceConfig := ctx.Value(odataCompliance).(OdataComplianceConfig)
   416  	if !hasComplianceConfig {
   417  		// Strict ODATA compliance by default.
   418  		cfg = ComplianceStrict
   419  	}
   420  	for len(tokens) > 0 {
   421  		token := tokens[0]
   422  		tokens = tokens[1:]
   423  		switch {
   424  		case p.isFunction(token):
   425  			previousTokenIsLiteral = false
   426  			if len(tokens) == 0 || tokens[0].Value != TokenOpenParen {
   427  				// A function token must be followed by open parenthesis token.
   428  				return nil, BadRequestError(fmt.Sprintf("Function '%s' must be followed by '('", token.Value))
   429  			}
   430  			incrementListArgCount(token)
   431  			// push functions onto the stack
   432  			stack.Push(token)
   433  		case p.isOperator(token):
   434  			previousTokenIsLiteral = false
   435  			// push operators onto stack according to precedence
   436  			o1 := p.Operators[token.Value]
   437  			if !stack.Empty() {
   438  				for o2, ok := p.Operators[stack.Peek().Value]; ok &&
   439  					((o1.Association == OpAssociationLeft && o1.Precedence <= o2.Precedence) ||
   440  						(o1.Association == OpAssociationRight && o1.Precedence < o2.Precedence)); {
   441  					queue.Enqueue(stack.Pop())
   442  
   443  					if stack.Empty() {
   444  						break
   445  					}
   446  					o2, ok = p.Operators[stack.Peek().Value]
   447  				}
   448  			}
   449  			if o1.Operands == 1 { // not, -
   450  				incrementListArgCount(token)
   451  			}
   452  			stack.Push(token)
   453  		case token.Value == TokenOpenParen:
   454  			previousTokenIsLiteral = false
   455  			// In OData, the parenthesis tokens can be used:
   456  			// - As a parenExpr to set explicit precedence order, such as "(a + 2) x b"
   457  			//   These precedence tokens are removed while parsing the OData query.
   458  			// - As a listExpr for multi-value sets, such as "City in ('San Jose', 'Chicago', 'Dallas')"
   459  			//   The list tokens are retained while parsing the OData query.
   460  			//   ABNF grammar:
   461  			//   listExpr  = OPEN BWS commonExpr BWS *( COMMA BWS commonExpr BWS ) CLOSE
   462  			incrementListArgCount(token)
   463  			// Push open parens onto the stack
   464  			stack.Push(token)
   465  		case token.Value == TokenCloseParen:
   466  			previousTokenIsLiteral = false
   467  			if previousToken != nil && previousToken.Value == TokenComma {
   468  				if cfg&ComplianceIgnoreInvalidComma == 0 {
   469  					return nil, fmt.Errorf("invalid token sequence: %s %s", previousToken.Value, token.Value)
   470  				}
   471  			}
   472  			// if we find a close paren, pop things off the stack
   473  			for !stack.Empty() {
   474  				if stack.Peek().Value == TokenOpenParen {
   475  					break
   476  				} else {
   477  					queue.Enqueue(stack.Pop())
   478  				}
   479  			}
   480  			if stack.Empty() {
   481  				// there was an error parsing
   482  				return nil, BadRequestError("Parse error. Mismatched parenthesis.")
   483  			}
   484  
   485  			// Determine if the parenthesis delimiters are:
   486  			// - A listExpr, possibly an empty list or single element.
   487  			//   Note a listExpr may be on the left-side or right-side of operators,
   488  			//   or it may be a list of function arguments.
   489  			// - A parenExpr, which is used as a precedence delimiter.
   490  			//
   491  			// (1, 2, 3) is a listExpr, there is no ambiguity.
   492  			// (1) matches both listExpr or parenExpr.
   493  			// parenExpr takes precedence over listExpr.
   494  			//
   495  			// For example:
   496  			//   1 IN (1, 2)  ==> parenthesis is used to create a list of two elements.
   497  			//   Tags(Key='Environment')/Value ==> variadic list of arguments in property navigation.
   498  			//   (1) + (2)    ==> parenthesis is a precedence delimiter, i.e. parenExpr.
   499  
   500  			// Get the argument count associated with the open paren.
   501  			// Examples:
   502  			// (a, b, c) is a listExpr with three arguments.
   503  			// (arg1='abc',arg2=123) is a listExpr with two arguments.
   504  			argCount := stack.getArgCount()
   505  			// pop off open paren
   506  			stack.Pop()
   507  
   508  			isListExpr := false
   509  			popTokenFromStack := false
   510  
   511  			if !stack.Empty() {
   512  				// Peek the token at the head of the stack.
   513  				if _, ok := p.Functions[stack.Peek().Value]; ok {
   514  					// The token is a function followed by a parenthesized expression.
   515  					// e.g. `func(a1, a2, a3)`
   516  					// ==> The parenthesized expression is a list expression.
   517  					popTokenFromStack = true
   518  					isListExpr = true
   519  				} else if o1, ok := p.Operators[stack.Peek().Value]; ok {
   520  					// The token is an operator followed by a parenthesized expression.
   521  					if o1.PreferListExpr {
   522  						// The expression is the right operand of an operator that has a preference for listExpr vs parenExpr.
   523  						isListExpr = true
   524  					}
   525  				} else {
   526  					if stack.Peek().Type == p.LiteralToken {
   527  						// The token is a odata identifier followed by a parenthesized expression.
   528  						// E.g. `Product(a1=abc)`:
   529  						// ==> The parenthesized expression is a list expression.
   530  						isListExpr = true
   531  						popTokenFromStack = true
   532  					}
   533  				}
   534  			}
   535  			if argCount > 1 {
   536  				isListExpr = true
   537  			}
   538  			// When a listExpr contains a single item, it is ambiguous whether it is a listExpr or parenExpr.
   539  			// For example:
   540  			// (1) add (2) ==> there is no list involved. There are superfluous parenthesis.
   541  			// (1, 2) in ( ('a', 'b', 'c'), (1, 2) ):
   542  			//    This is true because the LHS list (1, 2) is contained in the RHS list.
   543  			// The following expressions are not the same:
   544  			//   (1) in ( ('a', 'b', 'c'), (2), 1 )
   545  			//       ==> false because the LHS does not contain the LHS list (1).
   546  			//           or should (1) be simplified to the integer 1, which is contained in the RHS?
   547  			//   1 in ( ('a', 'b', 'c'), (2), 1 )
   548  			//       ==> true. The number 1 is contained in the RHS list.
   549  			if isListExpr {
   550  				// The open parenthesis was a delimiter for a listExpr.
   551  				// Add a token indicating the number of arguments in the list.
   552  				queue.Enqueue(&Token{
   553  					Value: strconv.Itoa(argCount),
   554  					Type:  TokenTypeArgCount,
   555  				})
   556  				// Enqueue a 'list' token if we are processing a ListExpr.
   557  				queue.Enqueue(&Token{
   558  					Value: TokenListExpr,
   559  					Type:  TokenTypeListExpr,
   560  				})
   561  			}
   562  			// if next token is a function or nav collection segment, move it to the queue
   563  			if popTokenFromStack {
   564  				queue.Enqueue(stack.Pop())
   565  			}
   566  		case token.Value == TokenComma:
   567  			previousTokenIsLiteral = false
   568  			if previousToken != nil {
   569  				switch previousToken.Value {
   570  				case TokenComma, TokenOpenParen:
   571  					return nil, fmt.Errorf("invalid token sequence: %s %s", previousToken.Value, token.Value)
   572  				}
   573  			}
   574  			// Function argument separator (",")
   575  			// Comma may be used as:
   576  			// 1. Separator of function parameters,
   577  			// 2. Separator for listExpr such as "City IN ('Seattle', 'San Francisco')"
   578  			//
   579  			// Pop off stack until we see a TokenOpenParen
   580  			for !stack.Empty() && stack.Peek().Value != TokenOpenParen {
   581  				// This happens when the previous function argument is an expression composed
   582  				// of multiple tokens, as opposed to a single token. For example:
   583  				//     max(sin( 5 mul pi ) add 3, sin( 5 ))
   584  				queue.Enqueue(stack.Pop())
   585  			}
   586  			if stack.Empty() {
   587  				// there was an error parsing. The top of the stack must be open parenthesis
   588  				return nil, BadRequestError("Parse error")
   589  			}
   590  			if stack.Peek().Value != TokenOpenParen {
   591  				panic("unexpected token")
   592  			}
   593  
   594  		default:
   595  			if previousTokenIsLiteral {
   596  				return nil, fmt.Errorf("invalid token sequence: %s %s", previousToken.Value, token.Value)
   597  			}
   598  			if token.Type == p.LiteralToken && len(tokens) > 0 && tokens[0].Value == TokenOpenParen {
   599  				// Literal followed by parenthesis ==> property collection navigation
   600  				// push property segment onto the stack
   601  				stack.Push(token)
   602  			} else {
   603  				// Token is a literal, number, string... -- put it in the queue
   604  				queue.Enqueue(token)
   605  			}
   606  			incrementListArgCount(token)
   607  			previousTokenIsLiteral = true
   608  		}
   609  		previousToken = token
   610  	}
   611  
   612  	// pop off the remaining operators onto the queue
   613  	for !stack.Empty() {
   614  		if stack.Peek().Value == TokenOpenParen || stack.Peek().Value == TokenCloseParen {
   615  			return nil, BadRequestError("parse error. Mismatched parenthesis.")
   616  		}
   617  		queue.Enqueue(stack.Pop())
   618  	}
   619  	return &queue, nil
   620  }
   621  
   622  // PostfixToTree converts a Postfix token queue to a parse tree
   623  func (p *Parser) PostfixToTree(ctx context.Context, queue *tokenQueue) (*ParseNode, error) {
   624  	stack := &nodeStack{}
   625  	currNode := &ParseNode{}
   626  
   627  	if queue == nil {
   628  		return nil, errors.New("input queue is nil")
   629  	}
   630  	t := queue.Head
   631  	for t != nil {
   632  		t = t.Next
   633  	}
   634  	// Function to process a list with a variable number of arguments.
   635  	processVariadicArgs := func(parent *ParseNode) (int, error) {
   636  
   637  		// Pop off the count of list arguments.
   638  		if stack.Empty() {
   639  			return 0, fmt.Errorf("no argCount token found, stack is empty")
   640  		}
   641  		n := stack.Pop()
   642  		if n.Token.Type != TokenTypeArgCount {
   643  			return 0, fmt.Errorf("expected arg count token, got '%v'", n.Token.Type)
   644  		}
   645  		argCount, err := strconv.Atoi(n.Token.Value)
   646  		if err != nil {
   647  			return 0, err
   648  		}
   649  		for i := 0; i < argCount; i++ {
   650  			if stack.Empty() {
   651  				return 0, fmt.Errorf("missing argument found. '%s'", parent.Token.Value)
   652  			}
   653  			c := stack.Pop()
   654  			// Attach the operand to its parent node which represents the function/operator
   655  			c.Parent = parent
   656  			// prepend children so they get added in the right order
   657  			parent.Children = append([]*ParseNode{c}, parent.Children...)
   658  		}
   659  		return argCount, nil
   660  	}
   661  	for !queue.Empty() {
   662  		// push the token onto the stack as a tree node
   663  		currToken := queue.Dequeue()
   664  		currNode = &ParseNode{currToken, nil, make([]*ParseNode, 0)}
   665  		stack.Push(currNode)
   666  
   667  		stackHeadToken := stack.Peek().Token
   668  		switch {
   669  		case p.isFunction(stackHeadToken):
   670  			// The top of the stack is a function, pop off the function.
   671  			node := stack.Pop()
   672  
   673  			// Pop off the list expression.
   674  			if stack.Empty() {
   675  				return nil, fmt.Errorf("no list expression token found, stack is empty")
   676  			}
   677  			n := stack.Pop()
   678  			if n.Token.Type != TokenTypeListExpr {
   679  				return nil, fmt.Errorf("expected list expression token, got '%v'", n.Token.Type)
   680  			}
   681  
   682  			if node.Token.Type == ExpressionTokenCase {
   683  				// Create argument pairs for case() statement by translating flat list into pairs
   684  				if len(n.Children)%2 != 0 {
   685  					return nil, fmt.Errorf("expected even number of comma-separated arguments to case statement")
   686  				}
   687  				for i:=0; i<len(n.Children); i+=2 {
   688  					if !p.isBooleanExpression(n.Children[i].Token) {
   689  						return nil, fmt.Errorf("expected boolean expression in case statement")
   690  					}
   691  					c := &ParseNode{
   692  						Token:    &Token{Type: ExpressionTokenCasePair},
   693  						Parent:   node,
   694  						Children: []*ParseNode{n.Children[i],n.Children[i+1]},
   695  					}
   696  					node.Children = append(node.Children, c)
   697  				}
   698  			} else {
   699  				// Collapse function arguments as direct children of function node
   700  				for _, c := range n.Children {
   701  					c.Parent = node
   702  				}
   703  				node.Children = n.Children
   704  			}
   705  
   706  			// Some functions, e.g. substring, can take a variable number of arguments. Enforce legal number of arguments
   707  			foundMatch := false
   708  			f := p.Functions[node.Token.Value]
   709  			for _, expectedArgCount := range f.Params {
   710  				if len(node.Children) == expectedArgCount {
   711  					foundMatch = true
   712  					break
   713  				}
   714  			}
   715  			if !foundMatch {
   716  				return nil, fmt.Errorf("invalid number of arguments for function '%s'. Got %d argument. Expected: %v",
   717  					node.Token.Value, len(node.Children), f.Params)
   718  			}
   719  			stack.Push(node)
   720  		case p.isOperator(stackHeadToken):
   721  			// if the top of the stack is an operator
   722  			node := stack.Pop()
   723  			o := p.Operators[node.Token.Value]
   724  			// pop off operands
   725  			for i := 0; i < o.Operands; i++ {
   726  				if stack.Empty() {
   727  					return nil, fmt.Errorf("insufficient number of operands for operator '%s'", node.Token.Value)
   728  				}
   729  				// prepend children so they get added in the right order
   730  				c := stack.Pop()
   731  				c.Parent = node
   732  				node.Children = append([]*ParseNode{c}, node.Children...)
   733  			}
   734  			stack.Push(node)
   735  		case TokenTypeListExpr == stackHeadToken.Type:
   736  			// ListExpr: List of items
   737  			// Pop off the list expression.
   738  			node := stack.Pop()
   739  			if _, err := processVariadicArgs(node); err != nil {
   740  				return nil, err
   741  			}
   742  			stack.Push(node)
   743  		case p.LiteralToken == stackHeadToken.Type:
   744  			// Pop off the property literal.
   745  			node := stack.Pop()
   746  
   747  			if !stack.Empty() && stack.Peek().Token.Type == TokenTypeListExpr {
   748  				// Pop off the list expression.
   749  				n := stack.Pop()
   750  				for _, c := range n.Children {
   751  					c.Parent = node
   752  				}
   753  				node.Children = n.Children
   754  			}
   755  			stack.Push(node)
   756  		}
   757  	}
   758  	// If all tokens have been processed, the stack should have zero or one element.
   759  	if stack.Head != nil && stack.Head.Prev != nil {
   760  		return nil, errors.New("invalid expression")
   761  	}
   762  	return currNode, nil
   763  }
   764  
   765  type tokenStack struct {
   766  	Head *tokenStackNode
   767  	Size int
   768  }
   769  
   770  type tokenStackNode struct {
   771  	Token        *Token          // The token value.
   772  	Prev         *tokenStackNode // The previous node in the stack.
   773  	listArgCount int             // The number of arguments in a listExpr.
   774  }
   775  
   776  func (s *tokenStack) Push(t *Token) {
   777  	node := tokenStackNode{Token: t, Prev: s.Head}
   778  	s.Head = &node
   779  	s.Size++
   780  }
   781  
   782  func (s *tokenStack) Pop() *Token {
   783  	node := s.Head
   784  	s.Head = node.Prev
   785  	s.Size--
   786  	return node.Token
   787  }
   788  
   789  // Peek returns the token at head of the stack.
   790  // The stack is not modified.
   791  // A panic occurs if the stack is empty.
   792  func (s *tokenStack) Peek() *Token {
   793  	return s.Head.Token
   794  }
   795  
   796  func (s *tokenStack) Empty() bool {
   797  	return s.Head == nil
   798  }
   799  
   800  func (s *tokenStack) getArgCount() int {
   801  	return s.Head.listArgCount
   802  }
   803  
   804  func (s *tokenStack) String() string {
   805  	output := ""
   806  	currNode := s.Head
   807  	for currNode != nil {
   808  		output = currNode.Token.Value + " " + output
   809  		currNode = currNode.Prev
   810  	}
   811  	return output
   812  }
   813  
   814  type tokenQueue struct {
   815  	Head *tokenQueueNode
   816  	Tail *tokenQueueNode
   817  }
   818  
   819  type tokenQueueNode struct {
   820  	Token *Token
   821  	Prev  *tokenQueueNode
   822  	Next  *tokenQueueNode
   823  }
   824  
   825  // Enqueue adds the specified token at the tail of the queue.
   826  func (q *tokenQueue) Enqueue(t *Token) {
   827  	node := tokenQueueNode{t, q.Tail, nil}
   828  	//fmt.Println(t.Value)
   829  
   830  	if q.Tail == nil {
   831  		q.Head = &node
   832  	} else {
   833  		q.Tail.Next = &node
   834  	}
   835  
   836  	q.Tail = &node
   837  }
   838  
   839  // Dequeue removes the token at the head of the queue and returns the token.
   840  func (q *tokenQueue) Dequeue() *Token {
   841  	node := q.Head
   842  	if node.Next != nil {
   843  		node.Next.Prev = nil
   844  	}
   845  	q.Head = node.Next
   846  	if q.Head == nil {
   847  		q.Tail = nil
   848  	}
   849  	return node.Token
   850  }
   851  
   852  func (q *tokenQueue) Empty() bool {
   853  	return q.Head == nil && q.Tail == nil
   854  }
   855  
   856  func (q *tokenQueue) String() string {
   857  	var sb strings.Builder
   858  	node := q.Head
   859  	for node != nil {
   860  		sb.WriteString(fmt.Sprintf("%s[%v]", node.Token.Value, node.Token.Type))
   861  		node = node.Next
   862  		if node != nil {
   863  			sb.WriteRune(' ')
   864  		}
   865  	}
   866  	return sb.String()
   867  }
   868  
   869  func (q *tokenQueue) GetValue() string {
   870  	var sb strings.Builder
   871  	node := q.Head
   872  	for node != nil {
   873  		sb.WriteString(node.Token.Value)
   874  		node = node.Next
   875  	}
   876  	return sb.String()
   877  }
   878  
   879  type nodeStack struct {
   880  	Head *nodeStackNode
   881  }
   882  
   883  type nodeStackNode struct {
   884  	ParseNode *ParseNode
   885  	Prev      *nodeStackNode
   886  }
   887  
   888  func (s *nodeStack) Push(n *ParseNode) {
   889  	node := nodeStackNode{ParseNode: n, Prev: s.Head}
   890  	s.Head = &node
   891  }
   892  
   893  func (s *nodeStack) Pop() *ParseNode {
   894  	node := s.Head
   895  	s.Head = node.Prev
   896  	return node.ParseNode
   897  }
   898  
   899  func (s *nodeStack) Peek() *ParseNode {
   900  	return s.Head.ParseNode
   901  }
   902  
   903  func (s *nodeStack) Empty() bool {
   904  	return s.Head == nil
   905  }
   906  
   907  func (s *nodeStack) String() string {
   908  	var sb strings.Builder
   909  	currNode := s.Head
   910  	for currNode != nil {
   911  		sb.WriteRune(' ')
   912  		sb.WriteString(currNode.ParseNode.Token.Value)
   913  		currNode = currNode.Prev
   914  	}
   915  	return sb.String()
   916  }