github.com/tomwright/dasel@v1.27.3/parse_selector.go (about) 1 package dasel 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 ) 8 9 // ParseSelector parses the given selector string and returns a Selector. 10 func ParseSelector(selector string) (Selector, error) { 11 sel := Selector{ 12 Raw: selector, 13 Current: "", 14 Remaining: "", 15 Type: "", 16 Property: "", 17 Conditions: make([]Condition, 0), 18 } 19 20 { 21 nextSelector, read := ExtractNextSelector(sel.Raw) 22 sel.Current = nextSelector 23 sel.Remaining = sel.Raw[read:] 24 } 25 26 nextSel := strings.TrimPrefix(sel.Current, ".") 27 var err error 28 29 switch { 30 case strings.HasPrefix(nextSel, "(?:") && strings.HasSuffix(nextSel, ")"): 31 sel, err = processParseSelectorSearch(nextSel, sel) 32 case strings.HasPrefix(nextSel, "(#:") && strings.HasSuffix(nextSel, ")"): 33 sel, err = processParseSelectorSearchOptional(nextSel, sel) 34 case strings.HasPrefix(nextSel, "(") && strings.HasSuffix(nextSel, ")"): 35 sel, err = processParseSelectorDynamic(nextSel, sel) 36 case nextSel == "[]": 37 sel, err = processParseSelectorNextAvailableIndex(nextSel, sel) 38 case nextSel == "[*]": 39 sel, err = processParseSelectorIndexAny(nextSel, sel) 40 case nextSel == "[#]": 41 sel, err = processParseSelectorLength(nextSel, sel) 42 case nextSel == "[@]": 43 sel, err = processParseSelectorType(nextSel, sel) 44 case strings.HasPrefix(nextSel, "[") && strings.HasSuffix(nextSel, "]"): 45 sel, err = processParseSelectorIndex(nextSel, sel) 46 default: 47 sel, err = processParseSelectorProperty(nextSel, sel) 48 } 49 50 return sel, err 51 } 52 53 func getCondition(parts DynamicSelectorParts) (Condition, error) { 54 switch parts.Key { 55 case "-", "keyValue": 56 switch parts.Comparison { 57 case "=": 58 return &KeyEqualCondition{ 59 Value: parts.Value, 60 }, nil 61 case "!=": 62 return &KeyEqualCondition{ 63 Value: parts.Value, 64 Not: true, 65 }, nil 66 default: 67 return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison} 68 } 69 default: 70 71 switch parts.Comparison { 72 case "=": 73 return &EqualCondition{ 74 Key: parts.Key, 75 Value: parts.Value, 76 }, nil 77 case "!=": 78 return &EqualCondition{ 79 Key: parts.Key, 80 Value: parts.Value, 81 Not: true, 82 }, nil 83 case ">=": 84 return &SortedComparisonCondition{ 85 Key: parts.Key, 86 Value: parts.Value, 87 Equal: true, 88 After: true, 89 }, nil 90 case ">": 91 return &SortedComparisonCondition{ 92 Key: parts.Key, 93 Value: parts.Value, 94 After: true, 95 }, nil 96 case "<=": 97 return &SortedComparisonCondition{ 98 Key: parts.Key, 99 Value: parts.Value, 100 Equal: true, 101 }, nil 102 case "<": 103 return &SortedComparisonCondition{ 104 Key: parts.Key, 105 Value: parts.Value, 106 }, nil 107 default: 108 return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison} 109 } 110 } 111 } 112 113 func processParseSelectorDynamic(selector string, sel Selector) (Selector, error) { 114 sel.Type = "DYNAMIC" 115 dynamicGroups, err := DynamicSelectorToGroups(selector) 116 if err != nil { 117 return sel, err 118 } 119 120 for _, g := range dynamicGroups { 121 parts := FindDynamicSelectorParts(g) 122 cond, err := getCondition(parts) 123 if err != nil { 124 return sel, err 125 } 126 if cond != nil { 127 sel.Conditions = append(sel.Conditions, cond) 128 } 129 } 130 131 return sel, nil 132 } 133 134 func processParseSelectorSearch(selector string, sel Selector) (Selector, error) { 135 sel.Type = "SEARCH" 136 137 dynamicGroups, err := DynamicSelectorToGroups(selector) 138 if err != nil { 139 return sel, err 140 } 141 if len(dynamicGroups) != 1 { 142 return sel, fmt.Errorf("require exactly 1 group in search selector") 143 } 144 145 for _, g := range dynamicGroups { 146 parts := FindDynamicSelectorParts(g) 147 parts.Key = strings.TrimPrefix(parts.Key, "?:") 148 cond, err := getCondition(parts) 149 if err != nil { 150 return sel, err 151 } 152 if cond != nil { 153 sel.Conditions = append(sel.Conditions, cond) 154 } 155 } 156 157 return sel, nil 158 } 159 160 func processParseSelectorSearchOptional(selector string, sel Selector) (Selector, error) { 161 sel.Type = "SEARCH_OPTIONAL" 162 163 dynamicGroups, err := DynamicSelectorToGroups(selector) 164 if err != nil { 165 return sel, err 166 } 167 168 for _, g := range dynamicGroups { 169 parts := FindDynamicSelectorParts(g) 170 parts.Key = strings.TrimPrefix(parts.Key, "#:") 171 cond, err := getCondition(parts) 172 if err != nil { 173 return sel, err 174 } 175 if cond != nil { 176 sel.Conditions = append(sel.Conditions, cond) 177 } 178 } 179 180 return sel, nil 181 } 182 183 func processParseSelectorNextAvailableIndex(selector string, sel Selector) (Selector, error) { 184 sel.Type = "NEXT_AVAILABLE_INDEX" 185 return sel, nil 186 } 187 188 func processParseSelectorIndexAny(selector string, sel Selector) (Selector, error) { 189 sel.Type = "INDEX_ANY" 190 return sel, nil 191 } 192 193 func processParseSelectorLength(selector string, sel Selector) (Selector, error) { 194 sel.Type = "LENGTH" 195 return sel, nil 196 } 197 198 func processParseSelectorType(selector string, sel Selector) (Selector, error) { 199 sel.Type = "TYPE" 200 return sel, nil 201 } 202 203 func processParseSelectorIndex(selector string, sel Selector) (Selector, error) { 204 sel.Type = "INDEX" 205 indexStr := selector[1 : len(selector)-1] 206 index, err := strconv.ParseInt(indexStr, 10, 32) 207 if err != nil { 208 return sel, &InvalidIndexErr{Index: indexStr} 209 } 210 sel.Index = int(index) 211 return sel, nil 212 } 213 214 func processParseSelectorProperty(selector string, sel Selector) (Selector, error) { 215 sel.Type = "PROPERTY" 216 sel.Property = selector 217 return sel, nil 218 }