...
Source file src/cmd/asm/internal/lex/tokenizer.go
1
2
3
4
5 package lex
6
7 import (
8 "io"
9 "os"
10 "strings"
11 "text/scanner"
12 "unicode"
13
14 "cmd/asm/internal/flags"
15 "cmd/internal/objabi"
16 "cmd/internal/src"
17 )
18
19
20
21
22 type Tokenizer struct {
23 tok ScanToken
24 s *scanner.Scanner
25 base *src.PosBase
26 line int
27 file *os.File
28 }
29
30 func NewTokenizer(name string, r io.Reader, file *os.File) *Tokenizer {
31 var s scanner.Scanner
32 s.Init(r)
33
34 s.Whitespace = 1<<'\t' | 1<<'\r' | 1<<' '
35
36 s.Mode = scanner.ScanChars |
37 scanner.ScanFloats |
38 scanner.ScanIdents |
39 scanner.ScanInts |
40 scanner.ScanStrings |
41 scanner.ScanComments
42 s.Position.Filename = name
43 s.IsIdentRune = isIdentRune
44 return &Tokenizer{
45 s: &s,
46 base: src.NewFileBase(name, objabi.AbsFile(objabi.WorkingDir(), name, *flags.TrimPath)),
47 line: 1,
48 file: file,
49 }
50 }
51
52
53 func isIdentRune(ch rune, i int) bool {
54 if unicode.IsLetter(ch) {
55 return true
56 }
57 switch ch {
58 case '_':
59 return true
60 case '\u00B7':
61 return true
62 case '\u2215':
63 return true
64 }
65
66 return i > 0 && unicode.IsDigit(ch)
67 }
68
69 func (t *Tokenizer) Text() string {
70 switch t.tok {
71 case LSH:
72 return "<<"
73 case RSH:
74 return ">>"
75 case ARR:
76 return "->"
77 case ROT:
78 return "@>"
79 }
80 return t.s.TokenText()
81 }
82
83 func (t *Tokenizer) File() string {
84 return t.base.Filename()
85 }
86
87 func (t *Tokenizer) Base() *src.PosBase {
88 return t.base
89 }
90
91 func (t *Tokenizer) SetBase(base *src.PosBase) {
92 t.base = base
93 }
94
95 func (t *Tokenizer) Line() int {
96 return t.line
97 }
98
99 func (t *Tokenizer) Col() int {
100 return t.s.Pos().Column
101 }
102
103 func (t *Tokenizer) Next() ScanToken {
104 s := t.s
105 for {
106 t.tok = ScanToken(s.Scan())
107 if t.tok != scanner.Comment {
108 break
109 }
110 length := strings.Count(s.TokenText(), "\n")
111 t.line += length
112
113
114 }
115 switch t.tok {
116 case '\n':
117 t.line++
118 case '-':
119 if s.Peek() == '>' {
120 s.Next()
121 t.tok = ARR
122 return ARR
123 }
124 case '@':
125 if s.Peek() == '>' {
126 s.Next()
127 t.tok = ROT
128 return ROT
129 }
130 case '<':
131 if s.Peek() == '<' {
132 s.Next()
133 t.tok = LSH
134 return LSH
135 }
136 case '>':
137 if s.Peek() == '>' {
138 s.Next()
139 t.tok = RSH
140 return RSH
141 }
142 }
143 return t.tok
144 }
145
146 func (t *Tokenizer) Close() {
147 if t.file != nil {
148 t.file.Close()
149 }
150 }
151
View as plain text