in modfile/read.go [511:617]
func (in *input) readToken() {
// Skip past spaces, stopping at non-space or EOF.
for !in.eof() {
c := in.peekRune()
if c == ' ' || c == '\t' || c == '\r' {
in.readRune()
continue
}
// Comment runs to end of line.
if in.peekPrefix("//") {
in.startToken()
// Is this comment the only thing on its line?
// Find the last \n before this // and see if it's all
// spaces from there to here.
i := bytes.LastIndex(in.complete[:in.pos.Byte], []byte("\n"))
suffix := len(bytes.TrimSpace(in.complete[i+1:in.pos.Byte])) > 0
in.readRune()
in.readRune()
// Consume comment.
for len(in.remaining) > 0 && in.readRune() != '\n' {
}
// If we are at top level (not in a statement), hand the comment to
// the parser as a _COMMENT token. The grammar is written
// to handle top-level comments itself.
if !suffix {
in.endToken(_COMMENT)
return
}
// Otherwise, save comment for later attachment to syntax tree.
in.endToken(_EOLCOMMENT)
in.comments = append(in.comments, Comment{in.token.pos, in.token.text, suffix})
return
}
if in.peekPrefix("/*") {
in.Error("mod files must use // comments (not /* */ comments)")
}
// Found non-space non-comment.
break
}
// Found the beginning of the next token.
in.startToken()
// End of file.
if in.eof() {
in.endToken(_EOF)
return
}
// Punctuation tokens.
switch c := in.peekRune(); c {
case '\n', '(', ')', '[', ']', '{', '}', ',':
in.readRune()
in.endToken(tokenKind(c))
return
case '"', '`': // quoted string
quote := c
in.readRune()
for {
if in.eof() {
in.pos = in.token.pos
in.Error("unexpected EOF in string")
}
if in.peekRune() == '\n' {
in.Error("unexpected newline in string")
}
c := in.readRune()
if c == quote {
break
}
if c == '\\' && quote != '`' {
if in.eof() {
in.pos = in.token.pos
in.Error("unexpected EOF in string")
}
in.readRune()
}
}
in.endToken(_STRING)
return
}
// Checked all punctuation. Must be identifier token.
if c := in.peekRune(); !isIdent(c) {
in.Error(fmt.Sprintf("unexpected input character %#q", c))
}
// Scan over identifier.
for isIdent(in.peekRune()) {
if in.peekPrefix("//") {
break
}
if in.peekPrefix("/*") {
in.Error("mod files must use // comments (not /* */ comments)")
}
in.readRune()
}
in.endToken(_IDENT)
}