Пакет scanner
Обзор
Пакет scanner предоставляет сканер и токенизатор для текста в кодировке UTF-8. Он принимает io.Reader, предоставляющий источник, который затем можно токенизировать повторными вызовами функции Scan. Для совместимости с существующими инструментами символ NUL не допускается. Если первый символ в источнике — метка порядка байтов (BOM), закодированная в UTF-8, она отбрасывается.
По умолчанию Scanner пропускает пробельные символы и комментарии Go и распознаёт все литералы, определённые спецификацией языка Go. Его можно настроить так, чтобы он распознавал только подмножество этих литералов, а также другие символы идентификаторов и пробельные символы.
Пример
Код:
const src = `
// This is scanned code.
if a > 10 {
someParsable = text
}`
var s scanner.Scanner
s.Init(strings.NewReader(src))
s.Filename = "example"
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
fmt.Printf("%s: %s\n", s.Position, s.TokenText())
}
Вывод:
example:3:1: if
example:3:4: a
example:3:6: >
example:3:8: 10
example:3:11: {
example:4:2: someParsable
example:4:15: =
example:4:17: text
example:5:1: }
Пример (IsIdentRune)
Код:
const src = "%var1 var2%"
var s scanner.Scanner
s.Init(strings.NewReader(src))
s.Filename = "default"
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
fmt.Printf("%s: %s\n", s.Position, s.TokenText())
}
fmt.Println()
s.Init(strings.NewReader(src))
s.Filename = "percent"
// treat leading '%' as part of an identifier
s.IsIdentRune = func(ch rune, i int) bool {
return ch == '%' && i == 0 || unicode.IsLetter(ch) || unicode.IsDigit(ch) && i > 0
}
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
fmt.Printf("%s: %s\n", s.Position, s.TokenText())
}
Вывод:
default:1:1: % default:1:2: var1 default:1:7: var2 default:1:11: % percent:1:1: %var1 percent:1:7: var2 percent:1:11: %
Пример (Mode)
Код:
const src = `
// Comment begins at column 5.
This line should not be included in the output.
/*
This multiline comment
should be extracted in
its entirety.
*/
`
var s scanner.Scanner
s.Init(strings.NewReader(src))
s.Filename = "comments"
s.Mode ^= scanner.SkipComments // don't skip comments
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
if strings.HasPrefix(txt, "//") || strings.HasPrefix(txt, "/*") {
fmt.Printf("%s: %s\n", s.Position, txt)
}
}
Вывод:
comments:2:5: // Comment begins at column 5. comments:6:1: /* This multiline comment should be extracted in its entirety. */
Пример (Whitespace)
Код:
// tab-separated values
const src = `aa ab ac ad
ba bb bc bd
ca cb cc cd
da db dc dd`
var (
col, row int
s scanner.Scanner
tsv [4][4]string // large enough for example above
)
s.Init(strings.NewReader(src))
s.Whitespace ^= 1<<'\t' | 1<<'\n' // don't skip tabs and new lines
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
switch tok {
case '\n':
row++
col = 0
case '\t':
col++
default:
tsv[row][col] = s.TokenText()
}
}
fmt.Print(tsv)
Вывод:
[[aa ab ac ad] [ba bb bc bd] [ca cb cc cd] [da db dc dd]]
Указатель
Файлы пакета
scanner.go
Константы
Предопределённые биты режима для управления распознаванием токенов. Например, чтобы настроить Scanner так, чтобы он распознавал только идентификаторы Go и целые числа, а также пропускал комментарии, установите поле Mode сканера в значение:
ScanIdents | ScanInts | ScanComments | SkipComments
За исключением комментариев, которые пропускаются, если установлен SkipComments, нераспознанные токены не игнорируются. Вместо этого сканер просто возвращает соответствующие отдельные символы (или, возможно, под-токены). Например, если режим — ScanIdents (а не ScanStrings), строка "foo" сканируется как последовательность токенов '"' Ident '"'.
Используйте GoTokens, чтобы настроить Scanner на приём всех токенов литералов Go, включая идентификаторы Go. Комментарии будут пропускаться.
const (
ScanIdents = 1 << -Ident
ScanInts = 1 << -Int
ScanFloats = 1 << -Float // includes Ints and hexadecimal floats
ScanChars = 1 << -Char
ScanStrings = 1 << -String
ScanRawStrings = 1 << -RawString
ScanComments = 1 << -Comment
SkipComments = 1 << -skipComment // if set with ScanComments, comments become white space
GoTokens = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
) Результатом Scan является один из этих токенов или символ Unicode.
const (
EOF = -(iota + 1)
Ident
Int
Float
Char
String
RawString
Comment
) GoWhitespace — значение по умолчанию для поля Whitespace у Scanner. Это значение выбирает пробельные символы Go.
const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '
func TokenString
func TokenString(tok rune) string
TokenString возвращает строку для отображения токена или символа Unicode.
type Position
Position — это значение, представляющее позицию в исходном тексте. Позиция допустима, если Line > 0.
type Position struct {
Filename string // filename, if any
Offset int // byte offset, starting at 0
Line int // line number, starting at 1
Column int // column number, starting at 1 (character count per line)
}
func (*Position) IsValid
func (pos *Position) IsValid() bool
IsValid сообщает, является ли позиция допустимой.
func (Position) String
func (pos Position) String() string
type Scanner
Scanner реализует чтение символов Unicode и токенов из io.Reader.
type Scanner struct {
// Error is called for each error encountered. If no Error
// function is set, the error is reported to os.Stderr.
Error func(s *Scanner, msg string)
// ErrorCount is incremented by one for each error encountered.
ErrorCount int
// The Mode field controls which tokens are recognized. For instance,
// to recognize Ints, set the ScanInts bit in Mode. The field may be
// changed at any time.
Mode uint
// The Whitespace field controls which characters are recognized
// as white space. To recognize a character ch <= ' ' as white space,
// set the ch'th bit in Whitespace (the Scanner's behavior is undefined
// for values ch > ' '). The field may be changed at any time.
Whitespace uint64
// IsIdentRune is a predicate controlling the characters accepted
// as the ith rune in an identifier. The set of valid characters
// must not intersect with the set of white space characters.
// If no IsIdentRune function is set, regular Go identifiers are
// accepted instead. The field may be changed at any time.
IsIdentRune func(ch rune, i int) bool // Go 1.4
// Start position of most recently scanned token; set by Scan.
// Calling Init or Next invalidates the position (Line == 0).
// The Filename field is always left untouched by the Scanner.
// If an error is reported (via Error) and Position is invalid,
// the scanner is not inside a token. Call Pos to obtain an error
// position in that case, or to obtain the position immediately
// after the most recently scanned token.
Position
// contains filtered or unexported fields
}
func (*Scanner) Init
func (s *Scanner) Init(src io.Reader) *Scanner
Init инициализирует Scanner новым источником и возвращает s. Значение Scanner.Error устанавливается в nil, Scanner.ErrorCount — в 0, Scanner.Mode — в GoTokens, а Scanner.Whitespace — в GoWhitespace.
func (*Scanner) Next
func (s *Scanner) Next() rune
Next читает и возвращает следующий символ Unicode. В конце источника возвращает EOF. Об ошибке чтения сообщает, вызывая s.Error, если она не равна nil; в противном случае выводит сообщение об ошибке в os.Stderr. Next не обновляет поле [Scanner.Position]; чтобы получить текущую позицию, используйте Scanner.Pos().
func (*Scanner) Peek
func (s *Scanner) Peek() rune
Peek возвращает следующий символ Unicode в источнике, не перемещая сканер. Возвращает EOF, если позиция сканера находится на последнем символе источника.
func (*Scanner) Pos
func (s *Scanner) Pos() (pos Position)
Pos возвращает позицию символа, непосредственно следующего за символом или токеном, возвращённым последним вызовом Scanner.Next или Scanner.Scan. Для начальной позиции последнего просканированного токена используйте поле [Scanner.Position].
func (*Scanner) Scan
func (s *Scanner) Scan() rune
Scan читает и возвращает следующий токен или символ Unicode из источника. Он распознаёт только те токены t, для которых установлен соответствующий бит Scanner.Mode (1<<-t). В конце источника возвращает EOF. Об ошибках сканера (ошибках чтения и токенов) сообщает, вызывая s.Error, если она не равна nil; в противном случае выводит сообщение об ошибке в os.Stderr.
func (*Scanner) TokenText
func (s *Scanner) TokenText() string
TokenText возвращает строку, соответствующую последнему просканированному токену. Доступен после вызова Scanner.Scan и при вызовах Scanner.Error.
© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/text/scanner/