]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/scanner: report at most one lexical error per number literal
authorRobert Griesemer <gri@golang.org>
Fri, 30 Aug 2019 00:34:17 +0000 (17:34 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 10 Sep 2019 03:10:11 +0000 (03:10 +0000)
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>
src/cmd/compile/internal/syntax/scanner.go
src/cmd/compile/internal/syntax/scanner_test.go

index 30ee6c0e5f788cbce8629ca3673d54d42e268b78..fef87171bc41cebb5ab6a1fb625b8877af4ff0d2 100644 (file)
@@ -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,17 +493,19 @@ 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' {
-               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)
+               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
@@ -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")
                }
index 3030bfd4c04daf1f117b5b4fd9be2d04647026d6..717deb9073f30605df4660a2dba81e5424098f91 100644 (file)
@@ -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)
+               }
+       }
+}