mirror of
https://github.com/golang/go
synced 2024-11-18 18:44:42 -07:00
cmd/compile/internal/scanner: report at most one lexical error per number literal
Leave reporting of multiple errors for strings alone for now; we probably want to see all incorrect escape sequences in runes/strings independent of other errors. Fixes #33961. Change-Id: Id722e95f802687963eec647d1d1841bd6ed17d35 Reviewed-on: https://go-review.googlesource.com/c/go/+/192499 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
a2cf16d42c
commit
cdd2c265cc
@ -35,8 +35,8 @@ type scanner struct {
|
||||
// current token, valid after calling next()
|
||||
line, col uint
|
||||
tok token
|
||||
lit string // valid if tok is _Name, _Literal, or _Semi ("semicolon", "newline", or "EOF")
|
||||
bad bool // valid if tok is _Literal, true if a syntax error occurred, lit may be incorrect
|
||||
lit string // valid if tok is _Name, _Literal, or _Semi ("semicolon", "newline", or "EOF"); may be malformed if bad is true
|
||||
bad bool // valid if tok is _Literal, true if a syntax error occurred, lit may be malformed
|
||||
kind LitKind // valid if tok is _Literal
|
||||
op Operator // valid if tok is _Operator, _AssignOp, or _IncOp
|
||||
prec int // valid if tok is _Operator, _AssignOp, or _IncOp
|
||||
@ -50,8 +50,6 @@ func (s *scanner) init(src io.Reader, errh func(line, col uint, msg string), mod
|
||||
|
||||
// errorf reports an error at the most recently read character position.
|
||||
func (s *scanner) errorf(format string, args ...interface{}) {
|
||||
// TODO(gri) Consider using s.bad to consistently suppress multiple errors
|
||||
// per token, here and below.
|
||||
s.bad = true
|
||||
s.error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
@ -495,18 +493,20 @@ func (s *scanner) number(c rune) {
|
||||
digsep |= ds
|
||||
}
|
||||
|
||||
if digsep&1 == 0 {
|
||||
if digsep&1 == 0 && !s.bad {
|
||||
s.errorf("%s has no digits", litname(prefix))
|
||||
}
|
||||
|
||||
// exponent
|
||||
if e := lower(c); e == 'e' || e == 'p' {
|
||||
if !s.bad {
|
||||
switch {
|
||||
case e == 'e' && prefix != 0 && prefix != '0':
|
||||
s.errorf("%q exponent requires decimal mantissa", c)
|
||||
case e == 'p' && prefix != 'x':
|
||||
s.errorf("%q exponent requires hexadecimal mantissa", c)
|
||||
}
|
||||
}
|
||||
c = s.getr()
|
||||
s.kind = FloatLit
|
||||
if c == '+' || c == '-' {
|
||||
@ -514,10 +514,10 @@ func (s *scanner) number(c rune) {
|
||||
}
|
||||
c, ds = s.digits(c, 10, nil)
|
||||
digsep |= ds
|
||||
if ds&1 == 0 {
|
||||
if ds&1 == 0 && !s.bad {
|
||||
s.errorf("exponent has no digits")
|
||||
}
|
||||
} else if prefix == 'x' && s.kind == FloatLit {
|
||||
} else if prefix == 'x' && s.kind == FloatLit && !s.bad {
|
||||
s.errorf("hexadecimal mantissa requires a 'p' exponent")
|
||||
}
|
||||
|
||||
@ -532,11 +532,11 @@ func (s *scanner) number(c rune) {
|
||||
s.lit = string(s.stopLit())
|
||||
s.tok = _Literal
|
||||
|
||||
if s.kind == IntLit && invalid >= 0 {
|
||||
if s.kind == IntLit && invalid >= 0 && !s.bad {
|
||||
s.errorAtf(invalid, "invalid digit %q in %s", s.lit[invalid], litname(prefix))
|
||||
}
|
||||
|
||||
if digsep&2 != 0 {
|
||||
if digsep&2 != 0 && !s.bad {
|
||||
if i := invalidSep(s.lit); i >= 0 {
|
||||
s.errorAtf(i, "'_' must separate successive digits")
|
||||
}
|
||||
|
@ -652,3 +652,25 @@ func TestIssue21938(t *testing.T) {
|
||||
t.Errorf("got %s %q; want %s %q", got.tok, got.lit, _Literal, ".5")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue33961(t *testing.T) {
|
||||
literals := `08__ 0b.p 0b_._p 0x.e 0x.p`
|
||||
for _, lit := range strings.Split(literals, " ") {
|
||||
n := 0
|
||||
var got scanner
|
||||
got.init(strings.NewReader(lit), func(_, _ uint, msg string) {
|
||||
// fmt.Printf("%s: %s\n", lit, msg) // uncomment for debugging
|
||||
n++
|
||||
}, 0)
|
||||
got.next()
|
||||
|
||||
if n != 1 {
|
||||
t.Errorf("%q: got %d errors; want 1", lit, n)
|
||||
continue
|
||||
}
|
||||
|
||||
if !got.bad {
|
||||
t.Errorf("%q: got error but bad not set", lit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user