github.com/team-ide/go-dialect@v1.9.20/dialect/statement_parser_expression.go (about) 1 package dialect 2 3 import ( 4 "errors" 5 "regexp" 6 "strconv" 7 "strings" 8 ) 9 10 var ( 11 operators = []string{"+", "-", "*", "/", "<=", ">=", "==", "<", ">"} 12 matchOperators = []string{"\\+", "\\-", "\\*", "/", "<=", ">=", "==", "<", ">"} 13 ) 14 15 func isOperator(str string) bool { 16 return StringsIndex(operators, str) >= 0 17 } 18 19 func splitOperator(content string) (res []string, err error) { 20 content = strings.TrimSpace(content) 21 if content == "" { 22 return 23 } 24 reg := regexp.MustCompile("[(" + strings.Join(matchOperators, ")(") + ")]+") 25 matches := reg.FindAllStringIndex(content, -1) 26 if len(matches) == 0 { 27 res = append(res, content) 28 return 29 } 30 lastIndex := 0 31 for _, match := range matches { 32 res = append(res, content[lastIndex:match[0]]) 33 res = append(res, content[match[0]:match[1]]) 34 lastIndex = match[1] 35 } 36 if len(content) > lastIndex { 37 res = append(res, content[lastIndex:]) 38 } 39 40 return 41 } 42 43 func parseExpressionStatement(content string, parent Statement) (expressionStatement *ExpressionStatement, err error) { 44 content = strings.TrimSpace(content) 45 46 var statements []Statement 47 48 var level int 49 var levelStatement = make(map[int]Statement) 50 var str string 51 52 var inStringPack string 53 var inStringLevel int 54 var stringPackChars = []string{"\"", "'"} 55 var lastChar string 56 var thisChar string 57 58 strList := strings.Split(content, "") 59 60 processStr := func(str string, statements *[]Statement, thisParent Statement) (err error) { 61 if str == "" { 62 return 63 } 64 var splitOperatorValues []string 65 splitOperatorValues, err = splitOperator(str) 66 if err != nil { 67 return 68 } 69 for _, one := range splitOperatorValues { 70 if one == "" { 71 continue 72 } 73 if isOperator(one) { 74 statement := &ExpressionOperatorStatement{ 75 Operator: one, 76 AbstractStatement: &AbstractStatement{ 77 Parent: thisParent, 78 Content: one, 79 }, 80 } 81 *statements = append(*statements, statement) 82 } else { 83 number, e := strconv.ParseFloat(one, 64) 84 if e != nil { 85 statement := &ExpressionIdentifierStatement{ 86 Identifier: one, 87 AbstractStatement: &AbstractStatement{ 88 Parent: thisParent, 89 Content: one, 90 }, 91 } 92 *statements = append(*statements, statement) 93 } else { 94 statement := &ExpressionNumberStatement{ 95 Value: number, 96 AbstractStatement: &AbstractStatement{ 97 Parent: thisParent, 98 Content: one, 99 }, 100 } 101 *statements = append(*statements, statement) 102 } 103 104 } 105 } 106 return 107 } 108 for i := 0; i < len(strList); i++ { 109 thisChar = strList[i] 110 111 if i > 0 { 112 lastChar = strList[i-1] 113 } 114 packCharIndex := StringsIndex(stringPackChars, thisChar) 115 var isStringEnd bool 116 var isStringStart bool 117 if packCharIndex >= 0 { 118 // inStringLevel == 0 表示 不在 字符串 包装 中 119 if inStringLevel == 0 { 120 inStringPack = stringPackChars[packCharIndex] 121 // 字符串包装层级 +1 122 inStringLevel++ 123 isStringStart = true 124 } else { 125 // 如果有转义符号 类似 “\'”,“\"” 126 if lastChar == "\\" { 127 } else if lastChar == inStringPack { 128 // 如果 前一个字符 与字符串包装字符一致 129 inStringLevel-- 130 } else { 131 // 字符串包装层级 -1 132 inStringLevel-- 133 } 134 if inStringLevel == 0 { 135 isStringEnd = true 136 } 137 } 138 } 139 var thisParentChildren *[]Statement 140 var thisParent = parent 141 if levelStatement[level] == nil { 142 thisParentChildren = &statements 143 } else { 144 thisParent = levelStatement[level].GetParent() 145 if thisParent == parent { 146 thisParentChildren = &statements 147 } else { 148 thisParentChildren = levelStatement[level].GetParent().GetChildren() 149 } 150 } 151 152 if isStringStart { 153 if levelStatement[level] != nil { 154 err = processStr(str, levelStatement[level].GetChildren(), thisParent) 155 if err != nil { 156 return 157 } 158 } else { 159 err = processStr(str, thisParentChildren, thisParent) 160 if err != nil { 161 return 162 } 163 } 164 str = "" 165 166 } else if isStringEnd { 167 stringValue := str 168 stringValue = strings.TrimSuffix(stringValue, stringPackChars[packCharIndex]) 169 stringValue = strings.TrimPrefix(stringValue, stringPackChars[packCharIndex]) 170 stringStatement := &ExpressionStringStatement{ 171 Value: stringValue, 172 AbstractStatement: &AbstractStatement{ 173 Parent: thisParent, 174 Content: str, 175 }, 176 } 177 if levelStatement[level] != nil { 178 *levelStatement[level].GetChildren() = append(*levelStatement[level].GetChildren(), stringStatement) 179 } else { 180 *thisParentChildren = append(*thisParentChildren, stringStatement) 181 } 182 str = "" 183 } else if inStringLevel == 0 { 184 if thisChar == "(" { 185 if thisParent == nil { 186 err = errors.New("sql template [" + content + "] parse match start error") 187 return 188 } 189 var statement Statement 190 var splitOperatorValues []string 191 splitOperatorValues, err = splitOperator(str) 192 if err != nil { 193 return 194 } 195 196 for i, one := range splitOperatorValues { 197 if one == "" { 198 continue 199 } 200 if i < len(splitOperatorValues)-1 || isOperator(one) { 201 err = processStr(one, thisParentChildren, thisParent) 202 if err != nil { 203 return 204 } 205 } else { 206 statement = &ExpressionFuncStatement{ 207 Func: one, 208 AbstractStatement: &AbstractStatement{ 209 Parent: thisParent, 210 Content: one, 211 }, 212 } 213 } 214 } 215 if statement == nil { 216 statement = &ExpressionBracketsStatement{ 217 AbstractStatement: &AbstractStatement{ 218 Parent: thisParent, 219 }, 220 } 221 } 222 *thisParentChildren = append(*thisParentChildren, statement) 223 level++ 224 levelStatement[level] = statement 225 str = "" 226 } else if thisChar == ")" { 227 if thisParent == nil || levelStatement[level] == nil { 228 err = errors.New("sql template [" + content + "] parse match end error") 229 return 230 } 231 err = processStr(str, levelStatement[level].GetChildren(), thisParent) 232 if err != nil { 233 return 234 } 235 levelStatement[level] = nil 236 level-- 237 str = "" 238 } else if thisChar == "," { 239 if thisParent == nil || levelStatement[level] == nil { 240 err = errors.New("sql template [" + content + "] parse match end error") 241 return 242 } 243 err = processStr(str, levelStatement[level].GetChildren(), thisParent) 244 if err != nil { 245 return 246 } 247 str = "" 248 } else { 249 str += thisChar 250 } 251 } else { 252 str += thisChar 253 } 254 } 255 if str != "" { 256 err = processStr(str, &statements, parent) 257 if err != nil { 258 return 259 } 260 } 261 expressionStatement = &ExpressionStatement{ 262 AbstractStatement: &AbstractStatement{ 263 Children: statements, 264 }, 265 } 266 return 267 }