diff --git a/pql/parser.go b/pql/parser.go index 0f1ff1e87..a5a72a0f7 100644 --- a/pql/parser.go +++ b/pql/parser.go @@ -174,6 +174,12 @@ func (p *Parser) parseArgs() (map[string]interface{}, error) { return nil, err } value = v + case FLOAT: + v, err := strconv.ParseFloat(lit, 64) + if err != nil { + return nil, err + } + value = v case LBRACK: v, err := p.parseList() if err != nil { diff --git a/pql/parser_test.go b/pql/parser_test.go index f4db973bc..23582594b 100644 --- a/pql/parser_test.go +++ b/pql/parser_test.go @@ -80,6 +80,24 @@ func TestParser_Parse(t *testing.T) { } }) + // Parse with float arguments. + t.Run("WithFloatArgs", func(t *testing.T) { + q, err := pql.ParseString(`MyCall( key=12.25, foo= 13.167)`) + if err != nil { + t.Fatal(err) + } else if !reflect.DeepEqual(q.Calls[0], + &pql.Call{ + Name: "MyCall", + Args: map[string]interface{}{ + "key": 12.25, + "foo": 13.167, + }, + }, + ) { + t.Fatalf("unexpected call: %#v", q.Calls[0]) + } + }) + // Parse with both child calls and arguments. t.Run("ChildrenAndArguments", func(t *testing.T) { q, err := pql.ParseString(`TopN(Bitmap(id=100, frame=other), frame=f, n=3)`) diff --git a/pql/scanner.go b/pql/scanner.go index 2b1add022..7cbbcc85b 100644 --- a/pql/scanner.go +++ b/pql/scanner.go @@ -143,17 +143,23 @@ func (s *Scanner) scanIdent() (tok Token, pos Pos, lit string) { // scanNumber consumes consecutive integer digits. func (s *Scanner) scanNumber() (tok Token, pos Pos, lit string) { pos = s.pos + tok = NUMBER var buf bytes.Buffer + var seenDot bool for { ch := s.read() - if !isDigit(ch) { + if !isDigit(ch) && (seenDot || ch != '.') { s.unread() break } + if ch == '.' { + seenDot = true + tok = FLOAT + } buf.WriteRune(ch) } - return NUMBER, pos, buf.String() + return tok, pos, buf.String() } // scanString consumes a single-quoted or double-quoted string. diff --git a/pql/scanner_test.go b/pql/scanner_test.go index 2f2112fe6..bc0cdd2f5 100644 --- a/pql/scanner_test.go +++ b/pql/scanner_test.go @@ -30,6 +30,7 @@ func TestScanner_Scan(t *testing.T) { {s: `foo`, tok: pql.IDENT, lit: `foo`}, {s: `100`, tok: pql.NUMBER, lit: `100`}, + {s: `100.3`, tok: pql.FLOAT, lit: `100.3`}, {s: `all`, tok: pql.ALL, lit: `all`}, {s: `ALL`, tok: pql.ALL, lit: `ALL`}, // case insensitive diff --git a/pql/token.go b/pql/token.go index f794a684a..af207e346 100644 --- a/pql/token.go +++ b/pql/token.go @@ -16,6 +16,7 @@ const ( STRING // "foo" BADSTRING // bad escape or unclosed string NUMBER // 12345 + FLOAT // 100.2 literal_end keyword_beg