From 68f665be7ac2221d1d7892b73357fb05e63e9f21 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Tue, 7 Apr 2026 15:09:45 +0800 Subject: [PATCH] CLI: Add float parsing (#13955) ### What problem does this PR solve? Add float parsing ### Type of change - [x] New Feature (non-breaking change which adds functionality) Signed-off-by: Jin Hai --- internal/cli/context_parser.go | 4 ++-- internal/cli/lexer.go | 20 ++++++++++++++++---- internal/cli/parser.go | 4 ++-- internal/cli/types.go | 3 ++- internal/cli/user_parser.go | 6 +++--- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/internal/cli/context_parser.go b/internal/cli/context_parser.go index 57ce897b95..4492109cb4 100644 --- a/internal/cli/context_parser.go +++ b/internal/cli/context_parser.go @@ -126,7 +126,7 @@ func (p *Parser) parseContextSearchCommand() (*Command, error) { if strings.ToLower(p.curToken.Value) == "n" { p.nextToken() var err error - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expect number") } cmd.Params["number"], err = p.parseNumber() @@ -140,7 +140,7 @@ func (p *Parser) parseContextSearchCommand() (*Command, error) { if strings.ToLower(p.curToken.Value) == "t" { p.nextToken() var err error - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expect number") } cmd.Params["threshold"], err = p.parseFloat() diff --git a/internal/cli/lexer.go b/internal/cli/lexer.go index 8986e8bdd0..b7777463a2 100644 --- a/internal/cli/lexer.go +++ b/internal/cli/lexer.go @@ -96,8 +96,7 @@ func (l *Lexer) NextToken() Token { ident := l.readIdentifier() return l.lookupIdent(ident) } else if isDigit(l.ch) { - tok.Type = TokenNumber - tok.Value = l.readNumber() + tok.Value, tok.Type = l.readNumber() return tok } @@ -129,12 +128,25 @@ func (l *Lexer) readIdentifier() string { return l.input[start:l.pos] } -func (l *Lexer) readNumber() string { +func (l *Lexer) readNumber() (string, int) { start := l.pos + tokenType := TokenInteger + + // Read integer part for isDigit(l.ch) { l.readChar() } - return l.input[start:l.pos] + + // If encountering a decimal point followed by a digit, read as float + if l.ch == '.' && isDigit(l.peekChar()) { + tokenType = TokenFloat + l.readChar() // Consume '.' + for isDigit(l.ch) { + l.readChar() + } + } + + return l.input[start:l.pos], tokenType } func (l *Lexer) readQuotedString(quote byte) string { diff --git a/internal/cli/parser.go b/internal/cli/parser.go index fc8fe4a7bb..f431f812bf 100644 --- a/internal/cli/parser.go +++ b/internal/cli/parser.go @@ -270,14 +270,14 @@ func (p *Parser) parseIdentifier() (string, error) { } func (p *Parser) parseNumber() (int, error) { - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return 0, fmt.Errorf("expected number, got %s", p.curToken.Value) } return strconv.Atoi(p.curToken.Value) } func (p *Parser) parseFloat() (float64, error) { - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return math.NaN(), fmt.Errorf("expected number, got %s", p.curToken.Value) } result, err := strconv.ParseFloat(p.curToken.Value, 64) diff --git a/internal/cli/types.go b/internal/cli/types.go index 391b83c8f2..31e55e5c4c 100644 --- a/internal/cli/types.go +++ b/internal/cli/types.go @@ -126,7 +126,8 @@ const ( // Literals TokenIdentifier TokenQuotedString - TokenNumber + TokenInteger + TokenFloat // Special TokenSemicolon diff --git a/internal/cli/user_parser.go b/internal/cli/user_parser.go index 41090217e1..61dfed6b0c 100644 --- a/internal/cli/user_parser.go +++ b/internal/cli/user_parser.go @@ -605,7 +605,7 @@ func (p *Parser) parseCreateIndex() (*Command, error) { } p.nextToken() - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expected vector size number, got %s", p.curToken.Value) } vectorSize, err := strconv.Atoi(p.curToken.Value) @@ -1922,7 +1922,7 @@ func (p *Parser) parseSearchCommand() (*Command, error) { if strings.ToLower(p.curToken.Value) == "n" { p.nextToken() var err error - if p.curToken.Type != TokenNumber { + if p.curToken.Type != TokenInteger { return nil, fmt.Errorf("expect number") } cmd.Params["number"], err = p.parseNumber() @@ -1936,7 +1936,7 @@ func (p *Parser) parseSearchCommand() (*Command, error) { //if strings.ToLower(p.curToken.Value) == "t" { // p.nextToken() // var err error - // if p.curToken.Type != TokenNumber { + // if p.curToken.Type != TokenInteger { // return nil, fmt.Errorf("expect number") // } // cmd.Params["threshold"], err = p.parseFloat()