|  | // Copyright 2018 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 scanner_test | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "strings" | 
|  | "text/scanner" | 
|  | "unicode" | 
|  | ) | 
|  |  | 
|  | func Example() { | 
|  | 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()) | 
|  | } | 
|  |  | 
|  | // Output: | 
|  | // 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: } | 
|  | } | 
|  |  | 
|  | func Example_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()) | 
|  | } | 
|  |  | 
|  | // Output: | 
|  | // 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: % | 
|  | } | 
|  |  | 
|  | func Example_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) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Output: | 
|  | // comments:2:5: // Comment begins at column 5. | 
|  | // comments:6:1: /* | 
|  | // This multiline comment | 
|  | // should be extracted in | 
|  | // its entirety. | 
|  | // */ | 
|  | } | 
|  |  | 
|  | func Example_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) | 
|  |  | 
|  | // Output: | 
|  | // [[aa ab ac ad] [ba bb bc bd] [ca cb cc cd] [da db dc dd]] | 
|  | } |