1package toml 2 3import ( 4 "fmt" 5 "strconv" 6 "unicode" 7) 8 9// Define tokens 10type tokenType int 11 12const ( 13 eof = -(iota + 1) 14) 15 16const ( 17 tokenError tokenType = iota 18 tokenEOF 19 tokenComment 20 tokenKey 21 tokenString 22 tokenInteger 23 tokenTrue 24 tokenFalse 25 tokenFloat 26 tokenEqual 27 tokenLeftBracket 28 tokenRightBracket 29 tokenLeftCurlyBrace 30 tokenRightCurlyBrace 31 tokenLeftParen 32 tokenRightParen 33 tokenDoubleLeftBracket 34 tokenDoubleRightBracket 35 tokenDate 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 "=", 59 "[", 60 "]", 61 "{", 62 "}", 63 "(", 64 ")", 65 "]]", 66 "[[", 67 "Date", 68 "KeyGroup", 69 "KeyGroupArray", 70 ",", 71 ":", 72 "$", 73 "*", 74 "?", 75 ".", 76 "..", 77 "EOL", 78} 79 80type token struct { 81 Position 82 typ tokenType 83 val string 84} 85 86func (tt tokenType) String() string { 87 idx := int(tt) 88 if idx < len(tokenTypeNames) { 89 return tokenTypeNames[idx] 90 } 91 return "Unknown" 92} 93 94func (t token) Int() int { 95 if result, err := strconv.Atoi(t.val); err != nil { 96 panic(err) 97 } else { 98 return result 99 } 100} 101 102func (t token) String() string { 103 switch t.typ { 104 case tokenEOF: 105 return "EOF" 106 case tokenError: 107 return t.val 108 } 109 110 return fmt.Sprintf("%q", t.val) 111} 112 113func isSpace(r rune) bool { 114 return r == ' ' || r == '\t' 115} 116 117func isAlphanumeric(r rune) bool { 118 return unicode.IsLetter(r) || r == '_' 119} 120 121func isKeyChar(r rune) bool { 122 // Keys start with the first character that isn't whitespace or [ and end 123 // with the last non-whitespace character before the equals sign. Keys 124 // cannot contain a # character." 125 return !(r == '\r' || r == '\n' || r == eof || r == '=') 126} 127 128func isKeyStartChar(r rune) bool { 129 return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') 130} 131 132func isDigit(r rune) bool { 133 return unicode.IsNumber(r) 134} 135 136func isHexDigit(r rune) bool { 137 return isDigit(r) || 138 (r >= 'a' && r <= 'f') || 139 (r >= 'A' && r <= 'F') 140} 141