forked from gookit/goutil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtokens.go
144 lines (121 loc) · 2.46 KB
/
tokens.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package textscan
import (
"github.com/gookit/goutil"
"github.com/gookit/goutil/errorx"
)
// Kind type
type Kind uint8
// String name for kind
func (k Kind) String() string {
return KindString(k)
}
// builtin defined kinds
const (
TokInvalid Kind = iota
TokKey
TokValue
TokComments
)
// global kinds
var kinds = map[Kind]string{
TokInvalid: "Invalid",
TokKey: "Key",
TokValue: "Value",
TokComments: "Comments",
}
// AddKind add global kind to kinds
func AddKind(k Kind, name string) {
if _, ok := kinds[k]; ok {
goutil.Panicf("cannot repeat register kind(%d): %s", int(k), name)
}
kinds[k] = name
}
// HasKind check
func HasKind(k Kind) bool {
_, ok := kinds[k]
return ok
}
// KindString name
func KindString(k Kind) string {
if name, ok := kinds[k]; ok {
return name
}
return "Invalid"
}
// IsKindToken check
func IsKindToken(k Kind, tok Token) bool {
if tok != nil {
return tok.Kind() == k
}
return false
}
// LiteToken interface
type LiteToken interface {
Kind() Kind
Value() string
IsValid() bool
}
// Token parser
type Token interface {
LiteToken
String() string
// HasMore is multi line values
HasMore() bool
// ScanMore scan multi line values
ScanMore(ts *TextScanner) error
MergeSame(tok Token) error
}
// BaseToken struct
type BaseToken struct {
kind Kind
value string
// Offset int // byte offset, starting at 0
// Line int // line number, starting at 1
// Column int // column number, starting at 1 (character count per line)
}
// Kind type
func (t *BaseToken) Kind() Kind {
return t.kind
}
// IsValid token
func (t *BaseToken) IsValid() bool {
return t.kind != TokInvalid
}
// Value of token
func (t *BaseToken) Value() string {
return t.value
}
// String of token
func (t *BaseToken) String() string {
if t.kind == TokInvalid {
return "<Invalid>"
}
return t.value
}
// StringToken struct
type StringToken struct {
BaseToken
}
// NewEmptyToken instance.
// Can use for want skip parse some contents
func NewEmptyToken() *StringToken {
return &StringToken{}
}
// NewStringToken instance.
func NewStringToken(k Kind, val string) *StringToken {
return &StringToken{
BaseToken{kind: k, value: val},
}
}
// HasMore is multi line values
func (t *StringToken) HasMore() bool {
return false
}
// ScanMore implements
func (t *StringToken) ScanMore(_ *TextScanner) error {
return nil
}
// MergeSame implements
func (t *StringToken) MergeSame(_ Token) error {
return errorx.Raw("cannot merge any token to Invalid token")
}