-
Notifications
You must be signed in to change notification settings - Fork 20
/
position.go
69 lines (59 loc) · 1.25 KB
/
position.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package scanner
import (
"fmt"
"unicode/utf8"
)
// Position represents a source position.
type Position struct {
// Filename is a name of file, if any
Filename string
// Offset is a byte offset, starting at 0
Offset int
// Line is a line number, starting at 1
Line int
// Column is a column number, starting at 1 (character count per line)
Column int
// columns is a map which the key is a line number and the value is a column number.
columns map[int]int
}
// NewPosition creates a new Position.
func NewPosition() *Position {
return &Position{
Offset: 0,
Line: 1,
Column: 1,
columns: make(map[int]int),
}
}
// String stringify the position.
func (pos Position) String() string {
s := pos.Filename
if s == "" {
s = "<input>"
}
s += fmt.Sprintf(":%d:%d", pos.Line, pos.Column)
return s
}
// Advance advances the position value.
func (pos *Position) Advance(r rune) {
len := utf8.RuneLen(r)
pos.Offset += len
if r == '\n' {
pos.columns[pos.Line] = pos.Column
pos.Line++
pos.Column = 1
} else {
pos.Column++
}
}
// Revert reverts the position value.
func (pos *Position) Revert(r rune) {
len := utf8.RuneLen(r)
pos.Offset -= len
if r == '\n' {
pos.Line--
pos.Column = pos.columns[pos.Line]
} else {
pos.Column--
}
}