Source File
read.go
Belonging Package
golang.org/x/mod/modfile
package modfile
import (
)
Span() (start, end Position)
Comment() *Comments
}
func ( *FileSyntax) ( Expr, ...string) *Line {
:
for := len(.Stmt) - 1; >= 0; -- {
:= .Stmt[]
switch stmt := .(type) {
case *Line:
if .Token != nil && .Token[0] == [0] {
=
break
}
case *LineBlock:
if .Token[0] == [0] {
=
break
}
}
}
}
:= func( int) *Line {
:= &Line{Token: }
if == len(.Stmt) {
.Stmt = append(.Stmt, )
} else {
.Stmt = append(.Stmt, nil)
copy(.Stmt[+2:], .Stmt[+1:])
.Stmt[+1] =
}
return
}
if != nil {
for , := range .Stmt {
switch stmt := .(type) {
case *Line:
if == {
if .Token == nil || .Token[0] != [0] {
return ()
}
.InBlock = true
:= &LineBlock{Token: .Token[:1], Line: []*Line{}}
.Token = .Token[1:]
.Stmt[] =
:= &Line{Token: [1:], InBlock: true}
.Line = append(.Line, )
return
}
case *LineBlock:
if == {
if .Token[0] != [0] {
return ()
}
:= &Line{Token: [1:], InBlock: true}
.Line = append(.Line, )
return
}
for , := range .Line {
if == {
if .Token[0] != [0] {
return ()
}
:= &Line{
Comments: Comments{
Before: commentsAdd(.Before, .Line[0].Before),
Suffix: commentsAdd(.Line[0].Suffix, .Suffix),
After: commentsAdd(.Line[0].After, .After),
},
Token: stringsAdd(.Token, .Line[0].Token),
}
.Stmt[] =
++
continue
}
.Line = .Line[:]
}
.Stmt[] =
++
}
.Stmt = .Stmt[:]
}
func (, []Comment) []Comment {
return append([:len():len()], ...)
}
func (, []string) []string {
return append([:len():len()], ...)
}
type CommentBlock struct {
Comments
Start Position
}
func ( *CommentBlock) () (, Position) {
return .Start, .Start
}
filename string // name of input file, for errors
complete []byte // entire input
remaining []byte // remaining input
tokenStart []byte // token being scanned to end of input
token token // next token to be returned by lex, peek
pos Position // current input position
comments []Comment // accumulated comments
file *FileSyntax // returned top-level syntax tree
parseErrors ErrorList // errors encountered during parsing
:= newInput(, )
defer func() {
if := recover(); != nil && != &.parseErrors {
.parseErrors = append(.parseErrors, Error{
Filename: .filename,
Pos: .pos,
Err: fmt.Errorf("internal error: %v", ),
})
}
if == nil && len(.parseErrors) > 0 {
= .parseErrors
}
}()
.readToken()
.parseFile()
if len(.parseErrors) > 0 {
return nil, .parseErrors
}
.file.Name = .filename
.assignComments()
return .file, nil
}
func ( *input) ( string) {
.parseErrors = append(.parseErrors, Error{
Filename: .filename,
Pos: .pos,
Err: errors.New(),
})
panic(&.parseErrors)
}
func ( *input) () int {
if len(.remaining) == 0 {
.Error("internal lexer error: readRune at EOF")
}
, := utf8.DecodeRune(.remaining)
.remaining = .remaining[:]
if == '\n' {
.pos.Line++
.pos.LineRune = 1
} else {
.pos.LineRune++
}
.pos.Byte +=
return int()
}
type token struct {
kind tokenKind
pos Position
endPos Position
text string
}
type tokenKind int
const (
_EOF tokenKind = -(iota + 1)
_EOLCOMMENT
_IDENT
_STRING
_COMMENT
)
func ( tokenKind) () bool {
return == _COMMENT || == _EOLCOMMENT
}
func ( tokenKind) () bool {
return == _EOF || == _EOLCOMMENT || == '\n'
}
if .peekPrefix("//") {
.startToken()
break
}
.startToken()
switch := .peekRune(); {
case '\n', '(', ')', '[', ']', '{', '}', ',':
.readRune()
.endToken(tokenKind())
return
case '"', '`': // quoted string
:=
.readRune()
for {
if .eof() {
.pos = .token.pos
.Error("unexpected EOF in string")
}
if .peekRune() == '\n' {
.Error("unexpected newline in string")
}
:= .readRune()
if == {
break
}
if == '\\' && != '`' {
if .eof() {
.pos = .token.pos
.Error("unexpected EOF in string")
}
.readRune()
}
}
.endToken(_STRING)
return
}
for isIdent(.peekRune()) {
if .peekPrefix("//") {
break
}
if .peekPrefix("/*") {
.Error("mod files must use // comments (not /* */ comments)")
}
.readRune()
}
.endToken(_IDENT)
}
switch .(type) {
case *FileSyntax:
continue
}
for , := range .post {
reverseComments(.Comment().Suffix)
}
func ( []Comment) {
for , := 0, len()-1; < ; , = +1, -1 {
[], [] = [], []
}
}
func ( *input) () {
.file = new(FileSyntax)
var *CommentBlock
for {
switch .peek() {
case '\n':
.lex()
if != nil {
.file.Stmt = append(.file.Stmt, )
= nil
}
case _COMMENT:
:= .lex()
if == nil {
= &CommentBlock{Start: .pos}
}
:= .Comment()
.Before = append(.Before, Comment{Start: .pos, Token: .text})
case _EOF:
if != nil {
.file.Stmt = append(.file.Stmt, )
}
return
default:
.parseStmt()
if != nil {
.file.Stmt[len(.file.Stmt)-1].Comment().Before = .Before
= nil
}
}
}
}
func ( *input) () {
:= .lex()
:= .pos
:= .endPos
:= []string{.text}
for {
:= .lex()
switch {
case .kind.isEOL():
.file.Stmt = append(.file.Stmt, &Line{
Start: ,
Token: ,
End: ,
})
return
case .kind == '(':
.lex()
.lex()
if len() == 0 && len(.Line) > 0 || len() > 0 && [len()-1].Token != "" {
= append(, Comment{})
}
case _COMMENT:
:= .lex()
= append(, Comment{Start: .pos, Token: .text})
case _EOF:
.Error(fmt.Sprintf("syntax error (unterminated block started at %s:%d:%d)", .filename, .Start.Line, .Start.LineRune))
case ')':
:= .lex()
.RParen.Before =
.RParen.Pos = .pos
if !.peek().isEOL() {
.Error("syntax error (expected newline after closing paren)")
}
.lex()
return
default:
:= .parseLine()
.Line = append(.Line, )
.Comment().Before =
= nil
}
}
}
func ( *input) () *Line {
:= .lex()
if .kind.isEOL() {
.Error("internal parse error: parseLine at end of line")
}
:= .pos
:= .endPos
:= []string{.text}
for {
:= .lex()
if .kind.isEOL() {
return &Line{
Start: ,
Token: ,
End: ,
InBlock: true,
}
}
= append(, .text)
= .endPos
}
}
var (
slashSlash = []byte("//")
moduleStr = []byte("module")
)
func ( []byte) string {
for len() > 0 {
:=
= nil
if := bytes.IndexByte(, '\n'); >= 0 {
, = [:], [+1:]
}
if := bytes.Index(, slashSlash); >= 0 {
= [:]
}
= bytes.TrimSpace()
if !bytes.HasPrefix(, moduleStr) {
continue
}
= [len(moduleStr):]
:= len()
= bytes.TrimSpace()
if len() == || len() == 0 {
continue
}
if [0] == '"' || [0] == '`' {
, := strconv.Unquote(string())
if != nil {
return "" // malformed quoted string or multiline module path
}
return
}
return string()
}
return "" // missing module path
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |