keysparsing.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Parsing keys handling both bare and quoted keys.
  2. package toml
  3. import (
  4. "bytes"
  5. "errors"
  6. "fmt"
  7. "unicode"
  8. )
  9. // Convert the bare key group string to an array.
  10. // The input supports double quotation to allow "." inside the key name,
  11. // but escape sequences are not supported. Lexers must unescape them beforehand.
  12. func parseKey(key string) ([]string, error) {
  13. groups := []string{}
  14. var buffer bytes.Buffer
  15. inQuotes := false
  16. wasInQuotes := false
  17. ignoreSpace := true
  18. expectDot := false
  19. for _, char := range key {
  20. if ignoreSpace {
  21. if char == ' ' {
  22. continue
  23. }
  24. ignoreSpace = false
  25. }
  26. switch char {
  27. case '"':
  28. if inQuotes {
  29. groups = append(groups, buffer.String())
  30. buffer.Reset()
  31. wasInQuotes = true
  32. }
  33. inQuotes = !inQuotes
  34. expectDot = false
  35. case '.':
  36. if inQuotes {
  37. buffer.WriteRune(char)
  38. } else {
  39. if !wasInQuotes {
  40. if buffer.Len() == 0 {
  41. return nil, errors.New("empty table key")
  42. }
  43. groups = append(groups, buffer.String())
  44. buffer.Reset()
  45. }
  46. ignoreSpace = true
  47. expectDot = false
  48. wasInQuotes = false
  49. }
  50. case ' ':
  51. if inQuotes {
  52. buffer.WriteRune(char)
  53. } else {
  54. expectDot = true
  55. }
  56. default:
  57. if !inQuotes && !isValidBareChar(char) {
  58. return nil, fmt.Errorf("invalid bare character: %c", char)
  59. }
  60. if !inQuotes && expectDot {
  61. return nil, errors.New("what?")
  62. }
  63. buffer.WriteRune(char)
  64. expectDot = false
  65. }
  66. }
  67. if inQuotes {
  68. return nil, errors.New("mismatched quotes")
  69. }
  70. if buffer.Len() > 0 {
  71. groups = append(groups, buffer.String())
  72. }
  73. if len(groups) == 0 {
  74. return nil, errors.New("empty key")
  75. }
  76. return groups, nil
  77. }
  78. func isValidBareChar(r rune) bool {
  79. return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r)
  80. }