1package toml
2
3import "fmt"
4
5// Define tokens
6type tokenType int
7
8const (
9	eof = -(iota + 1)
10)
11
12const (
13	tokenError tokenType = iota
14	tokenEOF
15	tokenComment
16	tokenKey
17	tokenString
18	tokenInteger
19	tokenTrue
20	tokenFalse
21	tokenFloat
22	tokenInf
23	tokenNan
24	tokenEqual
25	tokenLeftBracket
26	tokenRightBracket
27	tokenLeftCurlyBrace
28	tokenRightCurlyBrace
29	tokenLeftParen
30	tokenRightParen
31	tokenDoubleLeftBracket
32	tokenDoubleRightBracket
33	tokenDate
34	tokenLocalDate
35	tokenKeyGroup
36	tokenKeyGroupArray
37	tokenComma
38	tokenColon
39	tokenDollar
40	tokenStar
41	tokenQuestion
42	tokenDot
43	tokenDotDot
44	tokenEOL
45)
46
47var tokenTypeNames = []string{
48	"Error",
49	"EOF",
50	"Comment",
51	"Key",
52	"String",
53	"Integer",
54	"True",
55	"False",
56	"Float",
57	"Inf",
58	"NaN",
59	"=",
60	"[",
61	"]",
62	"{",
63	"}",
64	"(",
65	")",
66	"]]",
67	"[[",
68	"LocalDate",
69	"LocalDate",
70	"KeyGroup",
71	"KeyGroupArray",
72	",",
73	":",
74	"$",
75	"*",
76	"?",
77	".",
78	"..",
79	"EOL",
80}
81
82type token struct {
83	Position
84	typ tokenType
85	val string
86}
87
88func (tt tokenType) String() string {
89	idx := int(tt)
90	if idx < len(tokenTypeNames) {
91		return tokenTypeNames[idx]
92	}
93	return "Unknown"
94}
95
96func (t token) String() string {
97	switch t.typ {
98	case tokenEOF:
99		return "EOF"
100	case tokenError:
101		return t.val
102	}
103
104	return fmt.Sprintf("%q", t.val)
105}
106
107func isSpace(r rune) bool {
108	return r == ' ' || r == '\t'
109}
110
111func isAlphanumeric(r rune) bool {
112	return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_'
113}
114
115func isKeyChar(r rune) bool {
116	// Keys start with the first character that isn't whitespace or [ and end
117	// with the last non-whitespace character before the equals sign. Keys
118	// cannot contain a # character."
119	return !(r == '\r' || r == '\n' || r == eof || r == '=')
120}
121
122func isKeyStartChar(r rune) bool {
123	return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[')
124}
125
126func isDigit(r rune) bool {
127	return '0' <= r && r <= '9'
128}
129
130func isHexDigit(r rune) bool {
131	return isDigit(r) ||
132		(r >= 'a' && r <= 'f') ||
133		(r >= 'A' && r <= 'F')
134}
135