@@ -36,6 +36,7 @@ type scanner struct {
36
36
line , col uint
37
37
tok token
38
38
lit string // valid if tok is _Name, _Literal, or _Semi ("semicolon", "newline", or "EOF")
39
+ bad bool // valid if tok is _Literal, true if a syntax error occurred, lit may be incorrect
39
40
kind LitKind // valid if tok is _Literal
40
41
op Operator // valid if tok is _Operator, _AssignOp, or _IncOp
41
42
prec int // valid if tok is _Operator, _AssignOp, or _IncOp
@@ -47,10 +48,20 @@ func (s *scanner) init(src io.Reader, errh func(line, col uint, msg string), mod
47
48
s .nlsemi = false
48
49
}
49
50
51
+ // errorf reports an error at the most recently read character position.
50
52
func (s * scanner ) errorf (format string , args ... interface {}) {
53
+ // TODO(gri) Consider using s.bad to consistently suppress multiple errors
54
+ // per token, here and below.
55
+ s .bad = true
51
56
s .error (fmt .Sprintf (format , args ... ))
52
57
}
53
58
59
+ // errorAtf reports an error at a byte column offset relative to the current token start.
60
+ func (s * scanner ) errorAtf (offset int , format string , args ... interface {}) {
61
+ s .bad = true
62
+ s .errh (s .line , s .col + uint (offset ), fmt .Sprintf (format , args ... ))
63
+ }
64
+
54
65
// next advances the scanner by reading the next token.
55
66
//
56
67
// If a read, source encoding, or lexical error occurs, next calls
@@ -442,6 +453,7 @@ func (s *scanner) digits(c0 rune, base int, invalid *int) (c rune, digsep int) {
442
453
443
454
func (s * scanner ) number (c rune ) {
444
455
s .startLit ()
456
+ s .bad = false
445
457
446
458
base := 10 // number base
447
459
prefix := rune (0 ) // one of 0 (decimal), '0' (0-octal), 'x', 'o', or 'b'
@@ -477,14 +489,14 @@ func (s *scanner) number(c rune) {
477
489
if c == '.' {
478
490
s .kind = FloatLit
479
491
if prefix == 'o' || prefix == 'b' {
480
- s .error ("invalid radix point in " + litname (prefix ))
492
+ s .errorf ("invalid radix point in %s" , litname (prefix ))
481
493
}
482
494
c , ds = s .digits (s .getr (), base , & invalid )
483
495
digsep |= ds
484
496
}
485
497
486
498
if digsep & 1 == 0 {
487
- s .error ( litname ( prefix ) + " has no digits" )
499
+ s .errorf ( "%s has no digits", litname ( prefix ) )
488
500
}
489
501
490
502
// exponent
@@ -503,10 +515,10 @@ func (s *scanner) number(c rune) {
503
515
c , ds = s .digits (c , 10 , nil )
504
516
digsep |= ds
505
517
if ds & 1 == 0 {
506
- s .error ("exponent has no digits" )
518
+ s .errorf ("exponent has no digits" )
507
519
}
508
520
} else if prefix == 'x' && s .kind == FloatLit {
509
- s .error ("hexadecimal mantissa requires a 'p' exponent" )
521
+ s .errorf ("hexadecimal mantissa requires a 'p' exponent" )
510
522
}
511
523
512
524
// suffix 'i'
@@ -521,12 +533,12 @@ func (s *scanner) number(c rune) {
521
533
s .tok = _Literal
522
534
523
535
if s .kind == IntLit && invalid >= 0 {
524
- s .errh ( s . line , s . col + uint ( invalid ), fmt . Sprintf ( "invalid digit %q in %s" , s .lit [invalid ], litname (prefix ) ))
536
+ s .errorAtf ( invalid , "invalid digit %q in %s" , s .lit [invalid ], litname (prefix ))
525
537
}
526
538
527
539
if digsep & 2 != 0 {
528
540
if i := invalidSep (s .lit ); i >= 0 {
529
- s .errh ( s . line , s . col + uint ( i ) , "'_' must separate successive digits" )
541
+ s .errorAtf ( i , "'_' must separate successive digits" )
530
542
}
531
543
}
532
544
}
@@ -585,42 +597,38 @@ func invalidSep(x string) int {
585
597
586
598
func (s * scanner ) rune () {
587
599
s .startLit ()
600
+ s .bad = false
588
601
589
- ok := true // only report errors if we're ok so far
590
602
n := 0
591
603
for ; ; n ++ {
592
604
r := s .getr ()
593
605
if r == '\'' {
594
606
break
595
607
}
596
608
if r == '\\' {
597
- if ! s .escape ('\'' ) {
598
- ok = false
599
- }
609
+ s .escape ('\'' )
600
610
continue
601
611
}
602
612
if r == '\n' {
603
613
s .ungetr () // assume newline is not part of literal
604
- if ok {
605
- s .error ("newline in character literal" )
606
- ok = false
614
+ if ! s .bad {
615
+ s .errorf ("newline in character literal" )
607
616
}
608
617
break
609
618
}
610
619
if r < 0 {
611
- if ok {
612
- s .errh (s .line , s .col , "invalid character literal (missing closing ')" )
613
- ok = false
620
+ if ! s .bad {
621
+ s .errorAtf (0 , "invalid character literal (missing closing ')" )
614
622
}
615
623
break
616
624
}
617
625
}
618
626
619
- if ok {
627
+ if ! s . bad {
620
628
if n == 0 {
621
- s .error ("empty character literal or unescaped ' in character literal" )
629
+ s .errorf ("empty character literal or unescaped ' in character literal" )
622
630
} else if n != 1 {
623
- s .errh ( s . line , s . col , "invalid character literal (more than one character)" )
631
+ s .errorAtf ( 0 , "invalid character literal (more than one character)" )
624
632
}
625
633
}
626
634
@@ -632,6 +640,7 @@ func (s *scanner) rune() {
632
640
633
641
func (s * scanner ) stdString () {
634
642
s .startLit ()
643
+ s .bad = false
635
644
636
645
for {
637
646
r := s .getr ()
@@ -644,11 +653,11 @@ func (s *scanner) stdString() {
644
653
}
645
654
if r == '\n' {
646
655
s .ungetr () // assume newline is not part of literal
647
- s .error ("newline in string" )
656
+ s .errorf ("newline in string" )
648
657
break
649
658
}
650
659
if r < 0 {
651
- s .errh ( s . line , s . col , "string not terminated" )
660
+ s .errorAtf ( 0 , "string not terminated" )
652
661
break
653
662
}
654
663
}
@@ -661,14 +670,15 @@ func (s *scanner) stdString() {
661
670
662
671
func (s * scanner ) rawString () {
663
672
s .startLit ()
673
+ s .bad = false
664
674
665
675
for {
666
676
r := s .getr ()
667
677
if r == '`' {
668
678
break
669
679
}
670
680
if r < 0 {
671
- s .errh ( s . line , s . col , "string not terminated" )
681
+ s .errorAtf ( 0 , "string not terminated" )
672
682
break
673
683
}
674
684
}
@@ -741,7 +751,7 @@ func (s *scanner) skipComment(r rune) bool {
741
751
}
742
752
r = s .getr ()
743
753
}
744
- s .errh ( s . line , s . col , "comment not terminated" )
754
+ s .errorAtf ( 0 , "comment not terminated" )
745
755
return false
746
756
}
747
757
@@ -782,14 +792,14 @@ func (s *scanner) fullComment() {
782
792
}
783
793
}
784
794
785
- func (s * scanner ) escape (quote rune ) bool {
795
+ func (s * scanner ) escape (quote rune ) {
786
796
var n int
787
797
var base , max uint32
788
798
789
799
c := s .getr ()
790
800
switch c {
791
801
case 'a' , 'b' , 'f' , 'n' , 'r' , 't' , 'v' , '\\' , quote :
792
- return true
802
+ return
793
803
case '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' :
794
804
n , base , max = 3 , 8 , 255
795
805
case 'x' :
@@ -803,10 +813,10 @@ func (s *scanner) escape(quote rune) bool {
803
813
n , base , max = 8 , 16 , unicode .MaxRune
804
814
default :
805
815
if c < 0 {
806
- return true // complain in caller about EOF
816
+ return // complain in caller about EOF
807
817
}
808
- s .error ("unknown escape sequence" )
809
- return false
818
+ s .errorf ("unknown escape sequence" )
819
+ return
810
820
}
811
821
812
822
var x uint32
@@ -820,15 +830,15 @@ func (s *scanner) escape(quote rune) bool {
820
830
}
821
831
if d >= base {
822
832
if c < 0 {
823
- return true // complain in caller about EOF
833
+ return // complain in caller about EOF
824
834
}
825
835
kind := "hex"
826
836
if base == 8 {
827
837
kind = "octal"
828
838
}
829
839
s .errorf ("non-%s character in escape sequence: %c" , kind , c )
830
840
s .ungetr ()
831
- return false
841
+ return
832
842
}
833
843
// d < base
834
844
x = x * base + d
@@ -838,13 +848,10 @@ func (s *scanner) escape(quote rune) bool {
838
848
839
849
if x > max && base == 8 {
840
850
s .errorf ("octal escape value > 255: %d" , x )
841
- return false
851
+ return
842
852
}
843
853
844
854
if x > max || 0xD800 <= x && x < 0xE000 /* surrogate range */ {
845
- s .error ("escape sequence is invalid Unicode code point" )
846
- return false
855
+ s .errorf ("escape sequence is invalid Unicode code point %#U" , x )
847
856
}
848
-
849
- return true
850
857
}
0 commit comments