}
func (s *Scanner) error(msg string) {
+ s.tokEnd = s.srcPos - s.lastCharLen // make sure token text is terminated
s.ErrorCount++
if s.Error != nil {
s.Error(s, msg)
}
// TokenText returns the string corresponding to the most recently scanned token.
-// Valid after calling Scan().
+// Valid after calling Scan and in calls of Scanner.Error.
func (s *Scanner) TokenText() string {
if s.tokPos < 0 {
// no token text
return ""
}
- if s.tokEnd < 0 {
+ if s.tokEnd < s.tokPos {
// if EOF was reached, s.tokEnd is set to -1 (s.srcPos == 0)
s.tokEnd = s.tokPos
}
+ // s.tokEnd >= s.tokPos
if s.tokBuf.Len() == 0 {
// common case: the entire token text is still in srcBuf
func TestIllegalExponent(t *testing.T) {
const src = "1.5e 1.5E 1e+ 1e- 1.5z"
s := new(Scanner).Init(strings.NewReader(src))
+ s.Error = func(s *Scanner, msg string) {
+ const want = "illegal exponent"
+ if msg != want {
+ t.Errorf("%s: got error %q; want %q", s.TokenText(), msg, want)
+ }
+ }
checkTokErr(t, s, 1, Float, "1.5e")
checkTokErr(t, s, 1, Float, "1.5E")
checkTokErr(t, s, 1, Float, "1e+")
t.Errorf("scanner called Read %d times, not once", r)
}
}
+
+func TestIssue29723(t *testing.T) {
+ s := new(Scanner).Init(strings.NewReader(`x "`))
+ s.Error = func(s *Scanner, _ string) {
+ got := s.TokenText() // this call shouldn't panic
+ const want = `"`
+ if got != want {
+ t.Errorf("got %q; want %q", got, want)
+ }
+ }
+ for r := s.Scan(); r != EOF; r = s.Scan() {
+ }
+}