| 341 | } |
| 342 | |
| 343 | func (p *parser) parseNumber() (Value, error) { |
| 344 | start := p.pos |
| 345 | if p.pos < len(p.input) && (p.input[p.pos] == '-' || p.input[p.pos] == '+') { |
| 346 | p.pos++ |
| 347 | } |
| 348 | if p.pos >= len(p.input) || (p.input[p.pos] < '0' || p.input[p.pos] > '9') { |
| 349 | return Value{}, fmt.Errorf("expected number at position %d in %q", start, p.input) |
| 350 | } |
| 351 | isFloat := false |
| 352 | for p.pos < len(p.input) { |
| 353 | ch := p.input[p.pos] |
| 354 | if ch >= '0' && ch <= '9' { |
| 355 | p.pos++ |
| 356 | } else if ch == '.' && !isFloat { |
| 357 | isFloat = true |
| 358 | p.pos++ |
| 359 | } else if ch == 'f' && p.pos+1 <= len(p.input) { |
| 360 | // trailing 'f' for float literal compatibility with C++ expressions |
| 361 | p.pos++ |
| 362 | isFloat = true |
| 363 | break |
| 364 | } else { |
| 365 | break |
| 366 | } |
| 367 | } |
| 368 | lit := p.input[start:p.pos] |
| 369 | lit = strings.TrimSuffix(lit, "f") |
| 370 | if isFloat { |
| 371 | f, err := strconv.ParseFloat(lit, 64) |
| 372 | if err != nil { |
| 373 | return Value{}, fmt.Errorf("invalid float %q: %w", lit, err) |
| 374 | } |
| 375 | return FloatVal(f), nil |
| 376 | } |
| 377 | n, err := strconv.ParseInt(lit, 10, 64) |
| 378 | if err != nil { |
| 379 | return Value{}, fmt.Errorf("invalid int %q: %w", lit, err) |
| 380 | } |
| 381 | return IntVal(n), nil |
| 382 | } |
| 383 | |
| 384 | func (p *parser) safeCharAt(pos int) byte { |
| 385 | if pos >= len(p.input) { |