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 tokenLocalDate 34 tokenLocalTime 35 tokenTimeOffset 36 tokenKeyGroup 37 tokenKeyGroupArray 38 tokenComma 39 tokenColon 40 tokenDollar 41 tokenStar 42 tokenQuestion 43 tokenDot 44 tokenDotDot 45 tokenEOL 46) 47 48var tokenTypeNames = []string{ 49 "Error", 50 "EOF", 51 "Comment", 52 "Key", 53 "String", 54 "Integer", 55 "True", 56 "False", 57 "Float", 58 "Inf", 59 "NaN", 60 "=", 61 "[", 62 "]", 63 "{", 64 "}", 65 "(", 66 ")", 67 "]]", 68 "[[", 69 "LocalDate", 70 "LocalTime", 71 "TimeOffset", 72 "KeyGroup", 73 "KeyGroupArray", 74 ",", 75 ":", 76 "$", 77 "*", 78 "?", 79 ".", 80 "..", 81 "EOL", 82} 83 84type token struct { 85 Position 86 typ tokenType 87 val string 88} 89 90func (tt tokenType) String() string { 91 idx := int(tt) 92 if idx < len(tokenTypeNames) { 93 return tokenTypeNames[idx] 94 } 95 return "Unknown" 96} 97 98func (t token) String() string { 99 switch t.typ { 100 case tokenEOF: 101 return "EOF" 102 case tokenError: 103 return t.val 104 } 105 106 return fmt.Sprintf("%q", t.val) 107} 108 109func isSpace(r rune) bool { 110 return r == ' ' || r == '\t' 111} 112 113func isAlphanumeric(r rune) bool { 114 return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_' 115} 116 117func isKeyChar(r rune) bool { 118 // Keys start with the first character that isn't whitespace or [ and end 119 // with the last non-whitespace character before the equals sign. Keys 120 // cannot contain a # character." 121 return !(r == '\r' || r == '\n' || r == eof || r == '=') 122} 123 124func isKeyStartChar(r rune) bool { 125 return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') 126} 127 128func isDigit(r rune) bool { 129 return '0' <= r && r <= '9' 130} 131 132func isHexDigit(r rune) bool { 133 return isDigit(r) || 134 (r >= 'a' && r <= 'f') || 135 (r >= 'A' && r <= 'F') 136} 137