pos.mx raw
1 package token
2
3 const PosMax = 1 << 30
4 const Linebase = 1
5 const Colbase = 1
6
7 type Pos struct {
8 base *PosBase
9 line, col uint32
10 }
11
12 func MakePos(base *PosBase, line, col uint32) (p Pos) { return Pos{base, sat32(line), sat32(col)} }
13
14 func (pos Pos) Pos() (p Pos) { return pos }
15 func (pos Pos) IsKnown() (ok bool) { return pos.line > 0 }
16 func (pos Pos) Base() (p *PosBase) { return pos.base }
17 func (pos Pos) Line() (n uint32) { return pos.line }
18 func (pos Pos) Col() (n uint32) { return pos.col }
19
20 func (pos Pos) FileBase() (p *PosBase) {
21 b := pos.base
22 for b != nil && b != b.pos.base {
23 b = b.pos.base
24 }
25 return b
26 }
27
28 func (pos Pos) RelFilename() (s string) { return pos.base.Filename() }
29
30 func (pos Pos) RelLine() (n uint32) {
31 b := pos.base
32 if b.Line() == 0 {
33 return 0
34 }
35 return b.Line() + (pos.Line() - b.Pos().Line())
36 }
37
38 func (pos Pos) RelCol() (n uint32) {
39 b := pos.base
40 if b.Col() == 0 {
41 return 0
42 }
43 if pos.Line() == b.Pos().Line() {
44 return b.Col() + (pos.Col() - b.Pos().Col())
45 }
46 return pos.Col()
47 }
48
49 func (p Pos) Cmp(q Pos) (n int32) {
50 pname := p.RelFilename()
51 qname := q.RelFilename()
52 switch {
53 case pname < qname:
54 return -1
55 case pname > qname:
56 return +1
57 }
58
59 pline := p.Line()
60 qline := q.Line()
61 switch {
62 case pline < qline:
63 return -1
64 case pline > qline:
65 return +1
66 }
67
68 pcol := p.Col()
69 qcol := q.Col()
70 switch {
71 case pcol < qcol:
72 return -1
73 case pcol > qcol:
74 return +1
75 }
76
77 return 0
78 }
79
80 func (pos Pos) String() (s string) {
81 rel := position_{pos.RelFilename(), pos.RelLine(), pos.RelCol()}
82 abs := position_{pos.Base().Pos().RelFilename(), pos.Line(), pos.Col()}
83 s := rel.String()
84 if string(rel.filename) != string(abs.filename) || rel.line != abs.line || rel.col != abs.col {
85 s = s | "[" | abs.String() | "]"
86 }
87 return s
88 }
89
90 type position_ struct {
91 filename string
92 line, col uint32
93 }
94
95 func (p position_) String() (s string) {
96 if p.line == 0 {
97 if p.filename == "" {
98 return "<unknown position>"
99 }
100 return p.filename
101 }
102 if p.col == 0 {
103 return p.filename | ":" | ItoaU32(p.line)
104 }
105 return p.filename | ":" | ItoaU32(p.line) | ":" | ItoaU32(p.col)
106 }
107
108 func ItoaU32(n uint32) (s string) {
109 if n == 0 {
110 return "0"
111 }
112 buf := []byte{:0:10}
113 for n > 0 {
114 buf = append(buf, byte('0'+n%10))
115 n /= 10
116 }
117 for i, j := int32(0), len(buf)-1; i < j; i, j = i+1, j-1 {
118 buf[i], buf[j] = buf[j], buf[i]
119 }
120 return string(buf)
121 }
122
123 type PosBase struct {
124 pos Pos
125 filename string
126 line, col uint32
127 trimmed bool
128 }
129
130 func NewFileBase(filename string) (p *PosBase) {
131 return NewTrimmedFileBase(filename, false)
132 }
133
134 func NewTrimmedFileBase(filename string, trimmed bool) (p *PosBase) {
135 base := &PosBase{MakePos(nil, Linebase, Colbase), filename, Linebase, Colbase, trimmed}
136 base.pos.base = base
137 return base
138 }
139
140 func NewLineBase(pos Pos, filename string, trimmed bool, line, col uint32) (p *PosBase) {
141 return &PosBase{pos, filename, sat32(line), sat32(col), trimmed}
142 }
143
144 func (base *PosBase) IsFileBase() (ok bool) {
145 if base == nil {
146 return false
147 }
148 return base.pos.base == base
149 }
150
151 func (base *PosBase) Pos() (_ Pos) {
152 if base == nil {
153 return
154 }
155 return base.pos
156 }
157
158 func (base *PosBase) Filename() (s string) {
159 if base == nil {
160 return ""
161 }
162 return base.filename
163 }
164
165 func (base *PosBase) Line() (n uint32) {
166 if base == nil {
167 return 0
168 }
169 return base.line
170 }
171
172 func (base *PosBase) Col() (n uint32) {
173 if base == nil {
174 return 0
175 }
176 return base.col
177 }
178
179 func (base *PosBase) Trimmed() (ok bool) {
180 if base == nil {
181 return false
182 }
183 return base.trimmed
184 }
185
186 func sat32(x uint32) (n uint32) {
187 if x > PosMax {
188 return PosMax
189 }
190 return uint32(x)
191 }
192
193 func Itoa(n int32) (s string) {
194 if n == 0 {
195 return "0"
196 }
197 neg := false
198 if n < 0 {
199 neg = true
200 n = -n
201 }
202 buf := []byte{:0:12}
203 for n > 0 {
204 buf = append(buf, byte('0'+n%10))
205 n /= 10
206 }
207 if neg {
208 buf = append(buf, '-')
209 }
210 for i, j := int32(0), len(buf)-1; i < j; i, j = i+1, j-1 {
211 buf[i], buf[j] = buf[j], buf[i]
212 }
213 return string(buf)
214 }
215
216 func Itoa64(n int64) (s string) {
217 if n == 0 {
218 return "0"
219 }
220 neg := false
221 if n < 0 {
222 neg = true
223 n = -n
224 }
225 buf := []byte{:0:20}
226 for n > 0 {
227 buf = append(buf, byte('0'+n%10))
228 n /= 10
229 }
230 if neg {
231 buf = append(buf, '-')
232 }
233 for i, j := int32(0), len(buf)-1; i < j; i, j = i+1, j-1 {
234 buf[i], buf[j] = buf[j], buf[i]
235 }
236 return string(buf)
237 }
238
239 func Contains(tokset uint64, tok Token) (ok bool) {
240 var bit uint64 = 1
241 bit = bit << tok
242 return tokset&bit != 0
243 }
244