+++ /dev/null
-// Copyright 2025 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package scannerhooks defines nonexported channels between parser and scanner.
-// Ideally this package could be eliminated by adding API to scanner.
-package scannerhooks
-
-import "go/token"
-
-var StringEnd func(scanner any) token.Pos
"fmt"
"go/ast"
"go/build/constraint"
- "go/internal/scannerhooks"
"go/scanner"
"go/token"
"strings"
goVersion string // minimum Go version found in //go:build comment
// Next token
- pos token.Pos // token position
- tok token.Token // one token look-ahead
- lit string // token literal
- stringEnd token.Pos // position immediately after token; STRING only
+ pos token.Pos // token position
+ tok token.Token // one token look-ahead
+ lit string // token literal
// Error recovery
// (used to limit the number of calls to parser.advance
p.next()
}
+// end returns the end position of the current token
+func (p *parser) end() token.Pos {
+ return p.scanner.End()
+}
+
// ----------------------------------------------------------------------------
// Parsing support
continue
}
} else {
- if p.tok == token.STRING {
- p.stringEnd = scannerhooks.StringEnd(&p.scanner)
- }
-
// Found a non-comment; top of file is over.
p.top = false
}
var tag *ast.BasicLit
if p.tok == token.STRING {
- tag = &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.stringEnd, Kind: p.tok, Value: p.lit}
+ tag = &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.end(), Kind: p.tok, Value: p.lit}
p.next()
}
return x
case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
- end := p.pos + token.Pos(len(p.lit))
- if p.tok == token.STRING {
- end = p.stringEnd
- }
- x := &ast.BasicLit{ValuePos: p.pos, ValueEnd: end, Kind: p.tok, Value: p.lit}
+ x := &ast.BasicLit{ValuePos: p.pos, ValueEnd: p.end(), Kind: p.tok, Value: p.lit}
p.next()
return x
var path string
if p.tok == token.STRING {
path = p.lit
- end = p.stringEnd
+ end = p.end()
p.next()
} else if p.tok.IsLiteral() {
p.error(pos, "import path must be a string")
import (
"bytes"
"fmt"
- "go/internal/scannerhooks"
"go/token"
"path/filepath"
"strconv"
lineOffset int // current line offset
insertSemi bool // insert a semicolon before next newline
nlPos token.Pos // position of newline in preceding comment
- stringEnd token.Pos // end position; defined only for STRING tokens
endPosValid bool
endPos token.Pos // overrides the offset as the default end position
ErrorCount int // number of errors encountered
}
-// Provide go/parser with backdoor access to the StringEnd information.
-func init() {
- scannerhooks.StringEnd = func(scanner any) token.Pos {
- return scanner.(*Scanner).stringEnd
- }
-}
-
const (
bom = 0xFEFF // byte order mark, only permitted as very first character
eof = -1 // end of file
return c[:i]
}
-func (s *Scanner) scanRawString() (string, int) {
+func (s *Scanner) scanRawString() string {
// '`' opening already consumed
offs := s.offset - 1
}
lit := s.src[offs:s.offset]
- rawLen := len(lit)
if hasCR {
lit = stripCR(lit, false)
}
- return string(lit), rawLen
+ return string(lit)
}
func (s *Scanner) skipWhitespace() {
insertSemi = true
tok = token.STRING
lit = s.scanString()
- s.stringEnd = pos + token.Pos(len(lit))
case '\'':
insertSemi = true
tok = token.CHAR
case '`':
insertSemi = true
tok = token.STRING
- var rawLen int
- lit, rawLen = s.scanRawString()
- s.stringEnd = pos + token.Pos(rawLen)
+ lit = s.scanRawString()
case ':':
tok = s.switch2(token.COLON, token.DEFINE)
case '.':