import "scanner"

UTF-8でエンコードされたテキストの解析、トークン分割を行います。ソーステキストの供給源としてio.Readerを与え、そのあとソーステキストの終わりに達するまでScan関数を繰り返し呼び出して、トークンを取り出します。既存のツールとの互換性のため、NUL文字は許されません。(実装上の制約)

特に指定しない限り、ScannerはホワイトスペースとGo言語のコメントを読み飛ばし、Go言語の仕様で定義されているすべてのリテラルを認識します。それらリテラルのサブセットだけを認識するようにカスタマイズしたり、他の文字をホワイトスペースとして扱うようにカスタマイズすることができます。

基本的な使用パターンです。

var s scanner.Scanner
s.Init(src)
tok := s.Scan()
for tok != scanner.EOF {
	// tokを使い、何か処理を行う
	tok = s.Scan()
}

パッケージファイル

scanner.go

定数

事前に定義されているモードビットでトークンの認識対象を制御します。たとえば、Scannerの設定を変更し、識別子と整数だけを認識し、かつコメントをスキップするにはScannerのModeフィールドに次の値を設定します。

ScanIdents | ScanInts | SkipComments
const (
    ScanIdents     = 1 << -Ident
    ScanInts       = 1 << -Int
    ScanFloats     = 1 << -Float // Intsを含む
    ScanChars      = 1 << -Char
    ScanStrings    = 1 << -String
    ScanRawStrings = 1 << -RawString
    ScanComments   = 1 << -Comment
    SkipComments   = 1 << -skipComment // ScanCommentsとともにセットされると、コメントはホワイトスペースになります
    GoTokens       = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
)

Scanの戻り値は、下に示すトークン、もしくはUnicode文字です。

const (
    EOF = -(iota + 1)
    Ident
    Int
    Float
    Char
    String
    RawString
    Comment
)

GoWhitespaceは、ScannerのWhitespaceフィールドのデフォルト値です。この値はGo言語のホワイトスペース文字の判定に使います。

const GoWhitespace = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' '

TokenString関数

func TokenString(tok int) string

TokenStringは、トークンを表す文字列、またはUnicode文字を返します。

Position型

ソース内の位置は、Positionの値で表されます。Line > 0のとき有効です。

type Position struct {
    Filename string // ファイル名(あれば)
    Offset   int    // バイトオフセット。0から開始。
    Line     int    // 行番号。1から開始。
    Column   int    // カラム番号。0から開始。行内の文字数。
}

(*Position) IsValid関数

func (pos *Position) IsValid() bool

IsValidは、このPositionが有効なときtrueを返します。

(Position) String関数

func (pos Position) String() string

Scanner型

Scannerは、io.ReaderからUnicode文字とトークンを読み込む処理を実装しています。

type Scanner struct {

    // Errorは、エラーの度に呼び出されます。
    // エラー関数が設定されていないときは、エラーはos.Stderrに出力されます。
    Error func(s *Scanner, msg string)

    // ErrorCountは、エラーが発生する度にひとつインクリメントされます。
    ErrorCount int

    // Modeフィールドで、どのトークンを認識すべきか制御します。
    // たとえば、Intsを認識したいときは、ScanIntsビットをModeにセットします。
    // このフィールドの値はいつでも変更可能です。
    Mode uint

    // Whitespaceフィールドは、どの文字がホワイトスペースとして認識されるかを制御
    // します。文字chをホワイトスペースとして認識させるには、Whitespaceのch番目の
    // ビットを立てます。このとき、ch <= ' ' でなければならず、ch > ' ' のときの
    // スキャナの動作は未定義です。このフィールドの値はいつでも変更可能です。
    Whitespace uint64

    // カレントのトークンの位置です。Offset、Line、Columnフィールドは、
    // Scan()によってセットされます。
    // Filenameフィールドは、スキャナからは変更されません。
    Position
    // contains unexported fields
}

(*Scanner) Init関数

func (s *Scanner) Init(src io.Reader) *Scanner

Initは、Scannerを新しいソースで初期化して自分自身を返します。Errorフィールドはnil、ErrorCountフィールドは0、ModeフィールドはGoTokens、WhitespaceはGoWhitespaceに初期化されます。

(*Scanner) Next関数

func (s *Scanner) Next() int

Nextは、次のUnicodeを読み込んで返します。ソースの終わりに達したときはEOFを返します。読み込みエラーが起きたときは、s.Errorが設定されていればそこに設定されている関数を呼び出して報告し、設定されていなければos.Stderrにエラーメッセージを出力します。Nextは、ScannerのPositionフィールドを更新しないので、現在の位置を取得するときはPos()を使ってください。

(*Scanner) Peek関数

func (s *Scanner) Peek() int

Peekは、ソース内の次のUnicode文字を返します。このときスキャナの位置は進めません。スキャナの位置がソースの最後の文字のところにあるときは、EOFを返します。

(*Scanner) Pos関数

func (s *Scanner) Pos() Position

Posは、ソース内の現在位置を返します。Next()またはScan()の前に呼び出すと、これら関数を次に呼び出したときに返されるUnicode文字またはトークンの位置が返ります。これらの関数の後に呼び出したときは、直近で検査したトークンまたは文字のすぐ後ろの位置が返ります。

(*Scanner) Scan関数

func (s *Scanner) Scan() int

Scanは、次のトークンまたはUnicode文字をソースから読み込んで返します。あるトークンtがModeのビット値(1<<-t)にセットされているときだけ認識対象になります。ソースの終わりに達したときはEOFを返します。読み込みまたはトークンエラーが起きたときは、s.Errorが設定されていればそこに設定されている関数を呼び出して報告し、設定されていなければos.Stderrにエラーメッセージを出力します。

(*Scanner) TokenText関数

func (s *Scanner) TokenText() string

TokenTextは、直近で検査したトークンに一致する文字列を返します。このメソッドはScan()を呼び出したあとに有効となります。