vendor/github.com/pelletier/go-toml/keysparsing.go
changeset 265 05c40b36d3b2
parent 264 8f478162d991
child 266 80973a656b81
equal deleted inserted replaced
264:8f478162d991 265:05c40b36d3b2
     1 // Parsing keys handling both bare and quoted keys.
       
     2 
       
     3 package toml
       
     4 
       
     5 import (
       
     6 	"errors"
       
     7 	"fmt"
       
     8 )
       
     9 
       
    10 // Convert the bare key group string to an array.
       
    11 // The input supports double quotation and single quotation,
       
    12 // but escape sequences are not supported. Lexers must unescape them beforehand.
       
    13 func parseKey(key string) ([]string, error) {
       
    14 	runes := []rune(key)
       
    15 	var groups []string
       
    16 
       
    17 	if len(key) == 0 {
       
    18 		return nil, errors.New("empty key")
       
    19 	}
       
    20 
       
    21 	idx := 0
       
    22 	for idx < len(runes) {
       
    23 		for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
       
    24 			// skip leading whitespace
       
    25 		}
       
    26 		if idx >= len(runes) {
       
    27 			break
       
    28 		}
       
    29 		r := runes[idx]
       
    30 		if isValidBareChar(r) {
       
    31 			// parse bare key
       
    32 			startIdx := idx
       
    33 			endIdx := -1
       
    34 			idx++
       
    35 			for idx < len(runes) {
       
    36 				r = runes[idx]
       
    37 				if isValidBareChar(r) {
       
    38 					idx++
       
    39 				} else if r == '.' {
       
    40 					endIdx = idx
       
    41 					break
       
    42 				} else if isSpace(r) {
       
    43 					endIdx = idx
       
    44 					for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
       
    45 						// skip trailing whitespace
       
    46 					}
       
    47 					if idx < len(runes) && runes[idx] != '.' {
       
    48 						return nil, fmt.Errorf("invalid key character after whitespace: %c", runes[idx])
       
    49 					}
       
    50 					break
       
    51 				} else {
       
    52 					return nil, fmt.Errorf("invalid bare key character: %c", r)
       
    53 				}
       
    54 			}
       
    55 			if endIdx == -1 {
       
    56 				endIdx = idx
       
    57 			}
       
    58 			groups = append(groups, string(runes[startIdx:endIdx]))
       
    59 		} else if r == '\'' {
       
    60 			// parse single quoted key
       
    61 			idx++
       
    62 			startIdx := idx
       
    63 			for {
       
    64 				if idx >= len(runes) {
       
    65 					return nil, fmt.Errorf("unclosed single-quoted key")
       
    66 				}
       
    67 				r = runes[idx]
       
    68 				if r == '\'' {
       
    69 					groups = append(groups, string(runes[startIdx:idx]))
       
    70 					idx++
       
    71 					break
       
    72 				}
       
    73 				idx++
       
    74 			}
       
    75 		} else if r == '"' {
       
    76 			// parse double quoted key
       
    77 			idx++
       
    78 			startIdx := idx
       
    79 			for {
       
    80 				if idx >= len(runes) {
       
    81 					return nil, fmt.Errorf("unclosed double-quoted key")
       
    82 				}
       
    83 				r = runes[idx]
       
    84 				if r == '"' {
       
    85 					groups = append(groups, string(runes[startIdx:idx]))
       
    86 					idx++
       
    87 					break
       
    88 				}
       
    89 				idx++
       
    90 			}
       
    91 		} else if r == '.' {
       
    92 			idx++
       
    93 			if idx >= len(runes) {
       
    94 				return nil, fmt.Errorf("unexpected end of key")
       
    95 			}
       
    96 			r = runes[idx]
       
    97 			if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' {
       
    98 				return nil, fmt.Errorf("expecting key part after dot")
       
    99 			}
       
   100 		} else {
       
   101 			return nil, fmt.Errorf("invalid key character: %c", r)
       
   102 		}
       
   103 	}
       
   104 	if len(groups) == 0 {
       
   105 		return nil, fmt.Errorf("empty key")
       
   106 	}
       
   107 	return groups, nil
       
   108 }
       
   109 
       
   110 func isValidBareChar(r rune) bool {
       
   111 	return isAlphanumeric(r) || r == '-' || isDigit(r)
       
   112 }