Пакет scanner
Обзор
Пакет scanner предоставляет сканер и токенизатор для UTF-8-кодированного текста. Он принимает io.Reader, предоставляющий исходный текст, который затем может быть токенизирован посредством многократных вызовов функции Scan. Для совместимости с существующими инструментами, символ NUL запрещён. Если первый символ в исходном тексте представляет собой BOM (byte order mark) 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: %
Пример (Режим)
Код:
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. */
Пример (Пробелы)
Код:
// 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 | SkipComments
За исключением комментариев, которые пропускаются, если установлен SkipComments, нераспознанные токены не игнорируются. Вместо этого сканер просто возвращает соответствующие отдельные символы (или, возможно, подтокены). Например, если режим - ScanIdents (не ScanStrings), строка "foo" сканируется как последовательность токенов '"' Ident '"'.
Используйте GoTokens для настройки сканера таким образом, чтобы он принимал все литералы токенов 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<<' '
функция TokenString
func TokenString(tok rune) string
TokenString возвращает удобочитаемую строку для токена или Unicode символа.
тип 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)
}
функция (*Position) IsValid
func (pos *Position) IsValid() bool
IsValid проверяет, является ли позиция валидной.
функция (Position) String
func (pos Position) String() string
тип 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
}
функция (*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.
функция (*Scanner) Next
func (s *Scanner) Next() rune
Next читает и возвращает следующий Unicode символ. Возвращает EOF в конце исходного текста. Сообщает об ошибке чтения с помощью s.Error, если он не равен nil; в противном случае выводит сообщение об ошибке в os.Stderr. Next не обновляет поле [Scanner.Position]; используйте Scanner.Pos() для получения текущей позиции.
функция (*Scanner) Peek
func (s *Scanner) Peek() rune
Peek возвращает следующий Unicode символ в исходном тексте без продвижения сканера. Возвращает EOF, если позиция сканера находится в последнем символе исходного текста.
функция (*Scanner) Pos
func (s *Scanner) Pos() (pos Position)
Pos возвращает позицию символа, непосредственно следующего за символом или токеном, возвращённым последним вызовом Scanner.Next или Scanner.Scan. Используйте поле [Scanner.Position] для начальной позиции последнего отсканированного токена.
функция (*Scanner) Scan
func (s *Scanner) Scan() rune
Scan считывает следующий токен или Unicode символ из исходного текста и возвращает его. Распознаёт только токены t, для которых соответствующий бит [Scanner.Mode] (1<<-t) установлен. Возвращает EOF в конце исходного текста. Сообщает об ошибках сканера (ошибки чтения и токенов) с помощью вызова s.Error, если он не равен nil; в противном случае выводит сообщение об ошибке в os.Stderr.
функция (*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/