// TODO(gri) remove this code once math/big.Float.Parse can handle separators
as = strings.Replace(as, "_", "", -1) // strip separators
+ // TODO(gri) why is this needed?
for len(as) > 0 && (as[0] == ' ' || as[0] == '\t') {
as = as[1:]
}
- f, _, err := a.Val.Parse(as, 0)
- if err != nil {
- yyerror("malformed constant: %s (%v)", as, err)
- a.Val.SetFloat64(0)
- return
+ // Currently, Val.Parse below (== math/big.Float.Parse) does not
+ // handle the 0o-octal prefix which can appear with octal integers
+ // with 'i' suffix, which end up here as imaginary components of
+ // complex numbers. Handle explicitly for now.
+ // TODO(gri) remove once Float.Parse can handle octals (it handles 0b/0B)
+ var f *big.Float
+ if strings.HasPrefix(as, "0o") || strings.HasPrefix(as, "0O") {
+ x, ok := new(big.Int).SetString(as[2:], 8)
+ if !ok {
+ yyerror("malformed constant: %s", as)
+ a.Val.SetFloat64(0)
+ return
+ }
+ f = a.Val.SetInt(x)
+ } else {
+ var err error
+ f, _, err = a.Val.Parse(as, 0)
+ if err != nil {
+ yyerror("malformed constant: %s (%v)", as, err)
+ a.Val.SetFloat64(0)
+ return
+ }
}
if f.IsInf() {
{IntLit, "0b0190", "0b0190", "invalid digit '9' in binary literal"},
{IntLit, "0b01a0", "0b01 a0", ""}, // only accept 0-9
- // binary floats and imaginaries (invalid)
{FloatLit, "0b.", "0b.", "invalid radix point in binary literal"},
{FloatLit, "0b.1", "0b.1", "invalid radix point in binary literal"},
{FloatLit, "0b1.0", "0b1.0", "invalid radix point in binary literal"},
{FloatLit, "0b1e10", "0b1e10", "'e' exponent requires decimal mantissa"},
{FloatLit, "0b1P-1", "0b1P-1", "'P' exponent requires hexadecimal mantissa"},
- {ImagLit, "0b10i", "0b10i", "invalid suffix 'i' on binary literal"},
+
+ {ImagLit, "0b10i", "0b10i", ""},
+ {ImagLit, "0b10.0i", "0b10.0i", "invalid radix point in binary literal"},
// octals
{IntLit, "0o0", "0o0", ""},
{IntLit, "0o1293", "0o1293", "invalid digit '9' in octal literal"},
{IntLit, "0o12a3", "0o12 a3", ""}, // only accept 0-9
- // octal floats and imaginaries (invalid)
{FloatLit, "0o.", "0o.", "invalid radix point in octal literal"},
{FloatLit, "0o.2", "0o.2", "invalid radix point in octal literal"},
{FloatLit, "0o1.2", "0o1.2", "invalid radix point in octal literal"},
{FloatLit, "0o1E+2", "0o1E+2", "'E' exponent requires decimal mantissa"},
{FloatLit, "0o1p10", "0o1p10", "'p' exponent requires hexadecimal mantissa"},
- {ImagLit, "0o10i", "0o10i", "invalid suffix 'i' on octal literal"},
+
+ {ImagLit, "0o10i", "0o10i", ""},
+ {ImagLit, "0o10e0i", "0o10e0i", "'e' exponent requires decimal mantissa"},
// 0-octals
{IntLit, "0", "0", ""},
{IntLit, "1f", "1 f", ""}, // only accept 0-9
+ {ImagLit, "0i", "0i", ""},
+ {ImagLit, "0678i", "0678i", ""},
+
// decimal floats
{FloatLit, "0.", "0.", ""},
{FloatLit, "123.", "123.", ""},
{FloatLit, "0p0", "0p0", "'p' exponent requires hexadecimal mantissa"},
{FloatLit, "1.0P-1", "1.0P-1", "'P' exponent requires hexadecimal mantissa"},
- // decimal imaginaries
{ImagLit, "0.i", "0.i", ""},
{ImagLit, ".123i", ".123i", ""},
{ImagLit, "123.123i", "123.123i", ""},
{IntLit, "0x", "0x", "hexadecimal literal has no digits"},
{IntLit, "0x1g", "0x1 g", ""},
+ {ImagLit, "0xf00i", "0xf00i", ""},
+
// hexadecimal floats
{FloatLit, "0x0p0", "0x0p0", ""},
{FloatLit, "0x12efp-123", "0x12efp-123", ""},
{FloatLit, "0x1234PAB", "0x1234P AB", "exponent has no digits"},
{FloatLit, "0x1.2p1a", "0x1.2p1 a", ""},
- // hexadecimal imaginaries (invalid)
- {ImagLit, "0xf00i", "0xf00i", "invalid suffix 'i' on hexadecimal literal"},
- {ImagLit, "0xf00.bap+12i", "0xf00.bap+12i", "invalid suffix 'i' on hexadecimal literal"},
+ {ImagLit, "0xf00.bap+12i", "0xf00.bap+12i", ""},
// separators
{IntLit, "0b_1000_0001", "0b_1000_0001", ""},
// license that can be found in the LICENSE file.
// Test Go2 literal syntax for basic types.
-// TODO add more tests
+// Avoid running gofmt on this file to preserve the
+// test cases with upper-case prefixes (0B, 0O, 0X).
package main
}
}
-func equal(x, y float64) bool {
+func equal(x, y interface{}) bool {
if x != y {
fmt.Printf("%g != %g\n", x, y)
return false
assert(0_1 == 01)
assert(012 == 012)
assert(0_1_2 == 012)
+ assert(0_1_2i == complex(0, 12)) // decimal digits despite leading 0 for backward-compatibility
+ assert(00089i == complex(0, 89)) // decimal digits despite leading 0 for backward-compatibility
// decimals
assert(1_000_000 == 1000000)
+ assert(1_000i == complex(0, 1000))
// hexadecimals
assert(0x_1 == 0x1)
assert(0x1_2 == 0x12)
- assert(0X_cafe_f00d == 0xcafef00d)
+ assert(0x_cafe_f00d == 0xcafef00d)
+ assert(0x_cafei == complex(0, 0xcafe))
// octals
assert(0o_1 == 01)
assert(0o12 == 012)
- assert(0O_1_2 == 012)
+ assert(0o_1_2 == 012)
+ assert(0o_1_2i == complex(0, 0o12))
// binaries
assert(0b_1 == 1)
assert(0b10 == 2)
assert(0b_1_0 == 2)
+ assert(0b_1_0i == complex(0, 2))
// decimal floats
assert(0. == 0.0)
assert(1_0. == 10.0)
assert(.0_1 == 0.01)
assert(1_0.0_1 == 10.01)
+ assert(1_0.0_1i == complex(0, 10.01))
assert(0.e1_0 == 0.0e10)
assert(.0e1_0 == 0.0e10)
assert(1_0.e1_0 == 10.0e10)
assert(.0_1e1_0 == 0.01e10)
assert(1_0.0_1e1_0 == 10.01e10)
+ assert(1_0.0_1e1_0i == complex(0, 10.01e10))
// hexadecimal floats
assert(equal(0x1p-2, 0.25))
assert(equal(0x2.p10, 2048.0))
assert(equal(0x1.Fp+0, 1.9375))
- assert(equal(0X.8p-0, 0.5))
- assert(equal(0X1FFFP-16, 0.1249847412109375))
+ assert(equal(0x.8p-0, 0.5))
+ assert(equal(0x1FFFp-16, 0.1249847412109375))
assert(equal(0x1.fffffffffffffp1023, 1.7976931348623157e308))
+ assert(equal(0x1.fffffffffffffp1023i, complex(0, 1.7976931348623157e308)))
assert(equal(0x_1p-2, 0.25))
assert(equal(0x2.p1_0, 2048.0))
assert(equal(0x1_0.Fp+0, 16.9375))
- assert(equal(0X_0.8p-0, 0.5))
- assert(equal(0X_1FF_FP-16, 0.1249847412109375))
- assert(equal(0x1.f_ffff_ffff_ffffP1_023, 1.7976931348623157e308))
-
- // imaginaries
- assert(0i == complex(0, 0))
- assert(09i == complex(0, 9)) // "09i" is a decimal int followed by "i"
- assert(1.2e+3i == complex(0, 1.2e+3))
-
- assert(0_0i == complex(0, 0))
- assert(0_9i == complex(0, 9)) // "0_9i" is a decimal int followed by "i"
- assert(1.2_0e+0_3i == complex(0, 1.2e+3))
+ assert(equal(0x_0.8p-0, 0.5))
+ assert(equal(0x_1FF_Fp-16, 0.1249847412109375))
+ assert(equal(0x1.f_ffff_ffff_ffffp1_023, 1.7976931348623157e308))
+ assert(equal(0x1.f_ffff_ffff_ffffp1_023i, complex(0, 1.7976931348623157e308)))
}