(lval *sqlSymType)
| 551 | } |
| 552 | |
| 553 | func (s *scanner) scanIdent(lval *sqlSymType) { |
| 554 | s.pos-- |
| 555 | start := s.pos |
| 556 | isASCII := true |
| 557 | isLower := true |
| 558 | |
| 559 | // Consume the scanner character by character, stopping after the last legal |
| 560 | // identifier character. By the end of this function, we need to |
| 561 | // lowercase and unicode normalize this identifier, which is expensive if |
| 562 | // there are actual unicode characters in it. If not, it's quite cheap - and |
| 563 | // if it's lowercase already, there's no work to do. Therefore, we keep track |
| 564 | // of whether the string is only ASCII or only ASCII lowercase for later. |
| 565 | for { |
| 566 | ch := s.peek() |
| 567 | // fmt.Println(ch, ch >= utf8.RuneSelf, ch >= 'A' && ch <= 'Z') |
| 568 | |
| 569 | if ch >= utf8.RuneSelf { |
| 570 | isASCII = false |
| 571 | } else if ch >= 'A' && ch <= 'Z' { |
| 572 | isLower = false |
| 573 | } |
| 574 | |
| 575 | if !lex.IsIdentMiddle(ch) { |
| 576 | break |
| 577 | } |
| 578 | |
| 579 | s.pos++ |
| 580 | } |
| 581 | // fmt.Println("parsed: ", s.in[start:s.pos], isASCII, isLower) |
| 582 | |
| 583 | if isLower { |
| 584 | // Already lowercased - nothing to do. |
| 585 | lval.str = s.in[start:s.pos] |
| 586 | } else if isASCII { |
| 587 | // We know that the identifier we've seen so far is ASCII, so we don't need |
| 588 | // to unicode normalize. Instead, just lowercase as normal. |
| 589 | b := s.allocBytes(s.pos - start) |
| 590 | _ = b[s.pos-start-1] // For bounds check elimination. |
| 591 | for i, c := range s.in[start:s.pos] { |
| 592 | if c >= 'A' && c <= 'Z' { |
| 593 | c += 'a' - 'A' |
| 594 | } |
| 595 | b[i] = byte(c) |
| 596 | } |
| 597 | lval.str = *(*string)(unsafe.Pointer(&b)) |
| 598 | } else { |
| 599 | // The string has unicode in it. No choice but to run Normalize. |
| 600 | lval.str = lex.NormalizeName(s.in[start:s.pos]) |
| 601 | } |
| 602 | |
| 603 | isExperimental := false |
| 604 | kw := lval.str |
| 605 | switch { |
| 606 | case strings.HasPrefix(lval.str, "experimental_"): |
| 607 | kw = lval.str[13:] |
| 608 | isExperimental = true |
| 609 | case strings.HasPrefix(lval.str, "testing_"): |
| 610 | kw = lval.str[8:] |
no test coverage detected