Skip to content

Commit 3473aca

Browse files
committed
Merge branch 'master' of github.com:kevin-valerio/go-arithmetic-panik
2 parents a8b9bc2 + 086a1b4 commit 3473aca

File tree

18 files changed

+380
-88
lines changed

18 files changed

+380
-88
lines changed

api/next/74958.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg go/scanner, method (*Scanner) End() token.Pos #74958
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The scanner now allows retrieving the end position of a token via the new [Scanner.End] method.

src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/compile/internal/ssa/opGen.go

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/go/build/deps_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ var depsRules = `
342342
< internal/gover
343343
< go/version
344344
< go/token
345-
< go/internal/scannerhooks
346345
< go/scanner
347346
< go/ast
348347
< go/internal/typeparams;

src/go/internal/scannerhooks/hooks.go

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/go/parser/error_test.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.
8181

8282
for {
8383
pos, tok, lit := s.Scan()
84+
end := s.End()
85+
8486
switch tok {
8587
case token.EOF:
8688
return errors
@@ -104,13 +106,7 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.
104106
fallthrough
105107
default:
106108
prev = pos
107-
var l int // token length
108-
if tok.IsLiteral() {
109-
l = len(lit)
110-
} else {
111-
l = len(tok.String())
112-
}
113-
here = prev + token.Pos(l)
109+
here = end
114110
}
115111
}
116112
}

src/go/parser/parser.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"fmt"
2929
"go/ast"
3030
"go/build/constraint"
31-
"go/internal/scannerhooks"
3231
"go/scanner"
3332
"go/token"
3433
"strings"
@@ -53,10 +52,9 @@ type parser struct {
5352
goVersion string // minimum Go version found in //go:build comment
5453

5554
// Next token
56-
pos token.Pos // token position
57-
tok token.Token // one token look-ahead
58-
lit string // token literal
59-
stringEnd token.Pos // position immediately after token; STRING only
55+
pos token.Pos // token position
56+
tok token.Token // one token look-ahead
57+
lit string // token literal
6058

6159
// Error recovery
6260
// (used to limit the number of calls to parser.advance
@@ -87,6 +85,11 @@ func (p *parser) init(file *token.File, src []byte, mode Mode) {
8785
p.next()
8886
}
8987

88+
// end returns the end position of the current token
89+
func (p *parser) end() token.Pos {
90+
return p.scanner.End()
91+
}
92+
9093
// ----------------------------------------------------------------------------
9194
// Parsing support
9295

@@ -165,10 +168,6 @@ func (p *parser) next0() {
165168
continue
166169
}
167170
} else {
168-
if p.tok == token.STRING {
169-
p.stringEnd = scannerhooks.StringEnd(&p.scanner)
170-
}
171-
172171
// Found a non-comment; top of file is over.
173172
p.top = false
174173
}
@@ -726,7 +725,7 @@ func (p *parser) parseFieldDecl() *ast.Field {
726725

727726
var tag *ast.BasicLit
728727
if p.tok == token.STRING {
729-
tag = &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.stringEnd, Kind: p.tok, Value: p.lit}
728+
tag = &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.end(), Kind: p.tok, Value: p.lit}
730729
p.next()
731730
}
732731

@@ -1480,11 +1479,7 @@ func (p *parser) parseOperand() ast.Expr {
14801479
return x
14811480

14821481
case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
1483-
end := p.pos + token.Pos(len(p.lit))
1484-
if p.tok == token.STRING {
1485-
end = p.stringEnd
1486-
}
1487-
x := &ast.BasicLit{ValuePos: p.pos, ValueEnd: end, Kind: p.tok, Value: p.lit}
1482+
x := &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.end(), Kind: p.tok, Value: p.lit}
14881483
p.next()
14891484
return x
14901485

@@ -2525,7 +2520,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as
25252520
var path string
25262521
if p.tok == token.STRING {
25272522
path = p.lit
2528-
end = p.stringEnd
2523+
end = p.end()
25292524
p.next()
25302525
} else if p.tok.IsLiteral() {
25312526
p.error(pos, "import path must be a string")

src/go/scanner/scanner.go

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ package scanner
1010
import (
1111
"bytes"
1212
"fmt"
13-
"go/internal/scannerhooks"
1413
"go/token"
1514
"path/filepath"
1615
"strconv"
@@ -42,19 +41,14 @@ type Scanner struct {
4241
lineOffset int // current line offset
4342
insertSemi bool // insert a semicolon before next newline
4443
nlPos token.Pos // position of newline in preceding comment
45-
stringEnd token.Pos // end position; defined only for STRING tokens
44+
45+
endPosValid bool
46+
endPos token.Pos // overrides the offset as the default end position
4647

4748
// public state - ok to modify
4849
ErrorCount int // number of errors encountered
4950
}
5051

51-
// Provide go/parser with backdoor access to the StringEnd information.
52-
func init() {
53-
scannerhooks.StringEnd = func(scanner any) token.Pos {
54-
return scanner.(*Scanner).stringEnd
55-
}
56-
}
57-
5852
const (
5953
bom = 0xFEFF // byte order mark, only permitted as very first character
6054
eof = -1 // end of file
@@ -154,7 +148,9 @@ func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode
154148
err: err,
155149
mode: mode,
156150

157-
ch: ' ',
151+
ch: ' ',
152+
endPosValid: true,
153+
endPos: token.NoPos,
158154
}
159155

160156
s.next()
@@ -700,7 +696,7 @@ func stripCR(b []byte, comment bool) []byte {
700696
return c[:i]
701697
}
702698

703-
func (s *Scanner) scanRawString() (string, int) {
699+
func (s *Scanner) scanRawString() string {
704700
// '`' opening already consumed
705701
offs := s.offset - 1
706702

@@ -721,12 +717,11 @@ func (s *Scanner) scanRawString() (string, int) {
721717
}
722718

723719
lit := s.src[offs:s.offset]
724-
rawLen := len(lit)
725720
if hasCR {
726721
lit = stripCR(lit, false)
727722
}
728723

729-
return string(lit), rawLen
724+
return string(lit)
730725
}
731726

732727
func (s *Scanner) skipWhitespace() {
@@ -777,6 +772,21 @@ func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Tok
777772
return tok0
778773
}
779774

775+
// End returns the position immediately after the last scanned token.
776+
// If [Scanner.Scan] has not been called yet, End returns [token.NoPos].
777+
func (s *Scanner) End() token.Pos {
778+
// Handles special case:
779+
// - Makes sure we return [token.NoPos], even when [Scanner.Init] has consumed a BOM.
780+
// - When the previous token was a synthetic [token.SEMICOLON] inside a multi-line
781+
// comment, we make sure End returns its ending position (i.e. prevPos+len("\n")).
782+
if s.endPosValid {
783+
return s.endPos
784+
}
785+
786+
// Normal case: s.file.Pos(s.offset) represents the end of the token
787+
return s.file.Pos(s.offset)
788+
}
789+
780790
// Scan scans the next token and returns the token position, the token,
781791
// and its literal string if applicable. The source end is indicated by
782792
// [token.EOF].
@@ -790,7 +800,9 @@ func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Tok
790800
// If the returned token is [token.SEMICOLON], the corresponding
791801
// literal string is ";" if the semicolon was present in the source,
792802
// and "\n" if the semicolon was inserted because of a newline or
793-
// at EOF.
803+
// at EOF. If the newline is within a /*...*/ comment, the SEMICOLON token
804+
// is synthesized immediately after the COMMENT token; its position is that
805+
// of the actual newline within the comment.
794806
//
795807
// If the returned token is [token.ILLEGAL], the literal string is the
796808
// offending character.
@@ -809,10 +821,13 @@ func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Tok
809821
// and thus relative to the file set.
810822
func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) {
811823
scanAgain:
824+
s.endPosValid = false
812825
if s.nlPos.IsValid() {
813826
// Return artificial ';' token after /*...*/ comment
814827
// containing newline, at position of first newline.
815828
pos, tok, lit = s.nlPos, token.SEMICOLON, "\n"
829+
s.endPos = pos + 1
830+
s.endPosValid = true
816831
s.nlPos = token.NoPos
817832
return
818833
}
@@ -860,17 +875,14 @@ scanAgain:
860875
insertSemi = true
861876
tok = token.STRING
862877
lit = s.scanString()
863-
s.stringEnd = pos + token.Pos(len(lit))
864878
case '\'':
865879
insertSemi = true
866880
tok = token.CHAR
867881
lit = s.scanRune()
868882
case '`':
869883
insertSemi = true
870884
tok = token.STRING
871-
var rawLen int
872-
lit, rawLen = s.scanRawString()
873-
s.stringEnd = pos + token.Pos(rawLen)
885+
lit = s.scanRawString()
874886
case ':':
875887
tok = s.switch2(token.COLON, token.DEFINE)
876888
case '.':

0 commit comments

Comments
 (0)