( isExpr, allowEmpty bool, terminator1 int, terminators ...int, )
| 460 | } |
| 461 | |
| 462 | func (l *lexer) readSQLConstruct( |
| 463 | isExpr, allowEmpty bool, terminator1 int, terminators ...int, |
| 464 | ) (startPos, endPos, terminatorMet int, err error) { |
| 465 | if l.parser.Lookahead() != -1 { |
| 466 | // Push back the lookahead token so that it can be included. |
| 467 | l.PushBack(1) |
| 468 | } |
| 469 | parenLevel := 0 |
| 470 | startPos = l.lastPos + 1 |
| 471 | for l.lastPos < len(l.tokens) { |
| 472 | tok := l.Peek() |
| 473 | if tok.id == ERROR { |
| 474 | // This is a tokenizer (lexical) error: the scanner |
| 475 | // will have stored the error message in the string field. |
| 476 | return 0, 0, 0, errors.Newf("%s", tok.str) |
| 477 | } |
| 478 | if int(tok.id) == terminator1 && parenLevel == 0 { |
| 479 | terminatorMet = terminator1 |
| 480 | break |
| 481 | } |
| 482 | for _, term := range terminators { |
| 483 | if int(tok.id) == term && parenLevel == 0 { |
| 484 | terminatorMet = term |
| 485 | } |
| 486 | } |
| 487 | if terminatorMet != 0 { |
| 488 | break |
| 489 | } |
| 490 | if tok.id == '(' || tok.id == '[' { |
| 491 | parenLevel++ |
| 492 | } else if tok.id == ')' || tok.id == ']' { |
| 493 | parenLevel-- |
| 494 | if parenLevel < 0 { |
| 495 | return 0, 0, 0, errors.New("mismatched parentheses") |
| 496 | } |
| 497 | } |
| 498 | l.lastPos++ |
| 499 | } |
| 500 | if parenLevel != 0 { |
| 501 | return 0, 0, 0, errors.New("mismatched parentheses") |
| 502 | } |
| 503 | endPos = l.lastPos + 1 |
| 504 | if endPos > len(l.tokens) { |
| 505 | endPos = len(l.tokens) |
| 506 | } |
| 507 | if endPos < startPos || (!allowEmpty && endPos == startPos) { |
| 508 | if isExpr { |
| 509 | return 0, 0, 0, errors.New("missing expression") |
| 510 | } else { |
| 511 | return 0, 0, 0, errors.New("missing SQL statement") |
| 512 | } |
| 513 | } |
| 514 | return startPos, endPos, terminatorMet, nil |
| 515 | } |
| 516 | |
| 517 | func (l *lexer) getStr(startPos, endPos int) string { |
| 518 | if endPos <= startPos { |
no test coverage detected