forked from alecthomas/kingpin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.go
95 lines (81 loc) · 1.63 KB
/
lexer.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
package kingpin
import "strings"
type tokenType int
// Token types.
const (
TokenShort tokenType = iota
TokenLong
TokenArg
TokenEOF
)
var (
TokenEOFMarker = token{TokenEOF, ""}
)
type token struct {
Type tokenType
Value string
}
func (t *token) IsFlag() bool {
return t.Type == TokenShort || t.Type == TokenLong
}
func (t *token) IsEOF() bool {
return t.Type == TokenEOF
}
func (t *token) String() string {
switch t.Type {
case TokenShort:
return "-" + t.Value
case TokenLong:
return "--" + t.Value
case TokenArg:
return t.Value
case TokenEOF:
return "<EOF>"
default:
panic("unhandled type")
}
}
type tokens []*token
func (t tokens) String() string {
out := []string{}
for _, tok := range t {
out = append(out, tok.String())
}
return "Tokens{" + strings.Join(out, ", ") + "}"
}
func (t tokens) Next() (*token, tokens) {
if len(t) == 0 {
return &TokenEOFMarker, nil
}
return t[0], t[1:]
}
func (t tokens) Return(token *token) tokens {
if token.Type == TokenEOF {
return t
}
return append(tokens{token}, t...)
}
func (t tokens) Peek() *token {
if len(t) == 0 {
return &TokenEOFMarker
}
return t[0]
}
func Tokenize(args []string) (tokens tokens) {
for _, arg := range args {
if strings.HasPrefix(arg, "--") {
parts := strings.SplitN(arg[2:], "=", 2)
tokens = append(tokens, &token{TokenLong, parts[0]})
if len(parts) == 2 {
tokens = append(tokens, &token{TokenArg, parts[1]})
}
} else if strings.HasPrefix(arg, "-") {
for _, a := range arg[1:] {
tokens = append(tokens, &token{TokenShort, string(a)})
}
} else {
tokens = append(tokens, &token{TokenArg, arg})
}
}
return
}