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 }