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  }