github.com/go-graphite/carbonapi@v0.17.0/pkg/parser/parser.go (about)

     1  package parser
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  	"time"
    10  	"unicode"
    11  	"unicode/utf8"
    12  
    13  	"github.com/go-graphite/carbonapi/expr/holtwinters"
    14  
    15  	"github.com/ansel1/merry"
    16  )
    17  
    18  // expression parser
    19  
    20  type expr struct {
    21  	target    string
    22  	etype     ExprType
    23  	val       float64
    24  	valStr    string
    25  	args      []*expr // positional
    26  	namedArgs map[string]*expr
    27  	argString string
    28  }
    29  
    30  func (e *expr) IsName() bool {
    31  	return e.etype == EtName
    32  }
    33  
    34  func (e *expr) IsFunc() bool {
    35  	return e.etype == EtFunc
    36  }
    37  
    38  func (e *expr) IsConst() bool {
    39  	return e.etype == EtConst
    40  }
    41  
    42  func (e *expr) IsString() bool {
    43  	return e.etype == EtString
    44  }
    45  
    46  func (e *expr) IsBool() bool {
    47  	return e.etype == EtBool
    48  }
    49  
    50  func (e *expr) Type() ExprType {
    51  	return e.etype
    52  }
    53  
    54  func (e *expr) ToString() string {
    55  	switch e.etype {
    56  	case EtFunc:
    57  		return e.target + "(" + e.argString + ")"
    58  	case EtConst:
    59  		return e.valStr
    60  	case EtString:
    61  		s := e.valStr
    62  		s = strings.ReplaceAll(s, `\`, `\\`)
    63  		s = strings.ReplaceAll(s, `'`, `\'`)
    64  		return "'" + s + "'"
    65  	case EtBool:
    66  		return fmt.Sprint(e.val)
    67  	}
    68  
    69  	return e.target
    70  }
    71  
    72  func (e *expr) SetTarget(target string) {
    73  	e.target = target
    74  }
    75  
    76  func (e *expr) MutateTarget(target string) Expr {
    77  	e.SetTarget(target)
    78  	return e
    79  }
    80  
    81  func (e *expr) Target() string {
    82  	return e.target
    83  }
    84  
    85  func (e *expr) FloatValue() float64 {
    86  	return e.val
    87  }
    88  
    89  func (e *expr) StringValue() string {
    90  	return e.valStr
    91  }
    92  
    93  func (e *expr) SetValString(value string) {
    94  	e.valStr = value
    95  }
    96  
    97  func (e *expr) MutateValString(value string) Expr {
    98  	e.SetValString(value)
    99  	return e
   100  }
   101  
   102  func (e *expr) RawArgs() string {
   103  	return e.argString
   104  }
   105  
   106  func (e *expr) SetRawArgs(args string) {
   107  	e.argString = args
   108  }
   109  
   110  func (e *expr) MutateRawArgs(args string) Expr {
   111  	e.SetRawArgs(args)
   112  	return e
   113  }
   114  
   115  func (e *expr) Args() []Expr {
   116  	ret := make([]Expr, len(e.args))
   117  	for i := 0; i < len(e.args); i++ {
   118  		ret[i] = e.args[i]
   119  	}
   120  	return ret
   121  }
   122  
   123  func (e *expr) Arg(i int) Expr {
   124  	return e.args[i]
   125  }
   126  
   127  func (e *expr) ArgsLen() int {
   128  	return len(e.args)
   129  }
   130  
   131  func (e *expr) NamedArgs() map[string]Expr {
   132  	ret := make(map[string]Expr)
   133  	for k, v := range e.namedArgs {
   134  		ret[k] = v
   135  	}
   136  	return ret
   137  }
   138  
   139  func (e *expr) NamedArg(name string) (Expr, bool) {
   140  	expr, exist := e.namedArgs[name]
   141  	return expr, exist
   142  }
   143  
   144  func (e *expr) Metrics(from, until int64) []MetricRequest {
   145  	switch e.etype {
   146  	case EtName:
   147  		return []MetricRequest{{Metric: e.target, From: from, Until: until}}
   148  	case EtConst, EtString:
   149  		return nil
   150  	case EtFunc:
   151  		var r []MetricRequest
   152  		for _, a := range e.args {
   153  			r = append(r, a.Metrics(from, until)...)
   154  		}
   155  
   156  		switch e.target {
   157  		case "transformNull":
   158  			referenceSeriesExpr := e.GetNamedArg("referenceSeries")
   159  			if !referenceSeriesExpr.IsInterfaceNil() {
   160  				r = append(r, referenceSeriesExpr.Metrics(from, until)...)
   161  			}
   162  		case "consolidateBy":
   163  			function, err := e.GetStringArg(1)
   164  			if err != nil {
   165  				break
   166  			}
   167  			for i := range r {
   168  				r[i].ConsolidationFunc = function
   169  			}
   170  		case "timeShift":
   171  			offs, err := e.GetIntervalArg(1, -1)
   172  			if err != nil {
   173  				return nil
   174  			}
   175  			for i := range r {
   176  				r[i].From += int64(offs)
   177  				r[i].Until += int64(offs)
   178  			}
   179  		case "timeStack":
   180  			offs, err := e.GetIntervalArg(1, -1)
   181  			if err != nil {
   182  				return nil
   183  			}
   184  
   185  			start, err := e.GetIntArg(2)
   186  			if err != nil {
   187  				return nil
   188  			}
   189  
   190  			end, err := e.GetIntArg(3)
   191  			if err != nil {
   192  				return nil
   193  			}
   194  
   195  			var r2 []MetricRequest
   196  			for _, v := range r {
   197  				for i := int64(start); i < int64(end); i++ {
   198  					fromNew := v.From + i*int64(offs)
   199  					untilNew := v.Until + i*int64(offs)
   200  					r2 = append(r2, MetricRequest{
   201  						Metric: v.Metric,
   202  						From:   fromNew,
   203  						Until:  untilNew,
   204  					})
   205  				}
   206  			}
   207  
   208  			return r2
   209  		case "holtWintersForecast":
   210  			bootstrapInterval, err := e.GetIntervalNamedOrPosArgDefault("bootstrapInterval", 1, 1, holtwinters.DefaultBootstrapInterval)
   211  			if err != nil {
   212  				return nil
   213  			}
   214  
   215  			for i := range r {
   216  				r[i].From -= bootstrapInterval
   217  			}
   218  		case "holtWintersConfidenceBands", "holtWintersConfidenceArea":
   219  			bootstrapInterval, err := e.GetIntervalNamedOrPosArgDefault("bootstrapInterval", 2, 1, holtwinters.DefaultBootstrapInterval)
   220  			if err != nil {
   221  				return nil
   222  			}
   223  
   224  			for i := range r {
   225  				r[i].From -= bootstrapInterval
   226  			}
   227  		case "holtWintersAberration":
   228  			bootstrapInterval, err := e.GetIntervalNamedOrPosArgDefault("bootstrapInterval", 2, 1, holtwinters.DefaultBootstrapInterval)
   229  			if err != nil {
   230  				return nil
   231  			}
   232  
   233  			// For this function, we also need to pull data with an adjusted From time,
   234  			// so additional requests are added with the adjusted start time based on the
   235  			// bootstrapInterval
   236  			for i := range r {
   237  				adjustedReq := MetricRequest{
   238  					Metric: r[i].Metric,
   239  					From:   r[i].From - bootstrapInterval,
   240  					Until:  r[i].Until,
   241  				}
   242  				r = append(r, adjustedReq)
   243  			}
   244  		case "movingAverage", "movingMedian", "movingMin", "movingMax", "movingSum", "movingWindow", "exponentialMovingAverage":
   245  			if len(e.args) < 2 {
   246  				return nil
   247  			}
   248  			if e.args[1].etype == EtString {
   249  				offs, err := e.GetIntervalArg(1, 1)
   250  				if err != nil {
   251  					return nil
   252  				}
   253  				for i := range r {
   254  					fromNew := r[i].From - int64(offs)
   255  					r[i].From = fromNew
   256  				}
   257  			}
   258  		case "hitcount":
   259  			if len(e.args) < 2 {
   260  				return nil
   261  			}
   262  
   263  			alignToInterval, err := e.GetBoolNamedOrPosArgDefault("alignToInterval", 2, false)
   264  			if err != nil {
   265  				return nil
   266  			}
   267  			if alignToInterval {
   268  				bucketSizeInt32, err := e.GetIntervalArg(1, 1)
   269  				if err != nil {
   270  					return nil
   271  				}
   272  
   273  				interval := int64(bucketSizeInt32)
   274  				// This is done in order to replicate the behavior in Graphite web when alignToInterval is set,
   275  				// in which new data is fetched with the adjusted start time.
   276  				for i, _ := range r {
   277  					start := r[i].From
   278  					for _, v := range []int64{86400, 3600, 60} {
   279  						if interval >= v {
   280  							start -= start % v
   281  							break
   282  						}
   283  					}
   284  
   285  					r[i].From = start
   286  				}
   287  			}
   288  		case "smartSummarize":
   289  			if len(e.args) < 2 {
   290  				return nil
   291  			}
   292  
   293  			alignToInterval, err := e.GetStringNamedOrPosArgDefault("alignTo", 3, "")
   294  			if err != nil {
   295  				return nil
   296  			}
   297  
   298  			if alignToInterval != "" {
   299  				for i, _ := range r {
   300  					newStart, err := StartAlignTo(r[i].From, alignToInterval)
   301  					if err != nil {
   302  						return nil
   303  					}
   304  					r[i].From = newStart
   305  				}
   306  			}
   307  		}
   308  		return r
   309  	}
   310  
   311  	return nil
   312  }
   313  
   314  func (e *expr) GetIntervalArg(n, defaultSign int) (int32, error) {
   315  	if len(e.args) <= n {
   316  		return 0, ErrMissingArgument
   317  	}
   318  
   319  	if e.args[n].etype != EtString {
   320  		return 0, ErrBadType
   321  	}
   322  
   323  	seconds, err := IntervalString(e.args[n].valStr, defaultSign)
   324  	if err != nil {
   325  		return 0, ErrBadType
   326  	}
   327  
   328  	return seconds, nil
   329  }
   330  
   331  func (e *expr) GetIntervalNamedOrPosArgDefault(k string, n, defaultSign int, v int64) (int64, error) {
   332  	var val string
   333  	var err error
   334  	if a := e.getNamedArg(k); a != nil {
   335  		val, err = a.doGetStringArg()
   336  		if err != nil {
   337  			return 0, ErrBadType
   338  		}
   339  	} else {
   340  		if len(e.args) <= n {
   341  			return v, nil
   342  		}
   343  
   344  		if e.args[n].etype != EtString {
   345  			return 0, ErrBadType
   346  		}
   347  		val = e.args[n].valStr
   348  	}
   349  
   350  	seconds, err := IntervalString(val, defaultSign)
   351  	if err != nil {
   352  		return 0, ErrBadType
   353  	}
   354  
   355  	return int64(seconds), nil
   356  }
   357  
   358  func (e *expr) GetStringArg(n int) (string, error) {
   359  	if len(e.args) <= n {
   360  		return "", ErrMissingArgument
   361  	}
   362  
   363  	return e.args[n].doGetStringArg()
   364  }
   365  
   366  func (e *expr) GetStringArgs(n int) ([]string, error) {
   367  	if len(e.args) <= n {
   368  		return nil, ErrMissingArgument
   369  	}
   370  
   371  	strs := make([]string, 0, len(e.args)-n)
   372  
   373  	for i := n; i < len(e.args); i++ {
   374  		a, err := e.GetStringArg(i)
   375  		if err != nil {
   376  			return nil, err
   377  		}
   378  		strs = append(strs, a)
   379  	}
   380  
   381  	return strs, nil
   382  }
   383  
   384  func (e *expr) GetStringArgDefault(n int, s string) (string, error) {
   385  	if len(e.args) <= n {
   386  		return s, nil
   387  	}
   388  
   389  	return e.args[n].doGetStringArg()
   390  }
   391  
   392  func (e *expr) GetStringNamedOrPosArgDefault(k string, n int, s string) (string, error) {
   393  	if a := e.getNamedArg(k); a != nil {
   394  		return a.doGetStringArg()
   395  	}
   396  
   397  	return e.GetStringArgDefault(n, s)
   398  }
   399  
   400  func (e *expr) GetFloatArg(n int) (float64, error) {
   401  	if len(e.args) <= n {
   402  		return 0, ErrMissingArgument
   403  	}
   404  
   405  	return e.args[n].doGetFloatArg()
   406  }
   407  
   408  func (e *expr) GetFloatArgDefault(n int, v float64) (float64, error) {
   409  	if len(e.args) <= n {
   410  		return v, nil
   411  	}
   412  
   413  	return e.args[n].doGetFloatArg()
   414  }
   415  
   416  func (e *expr) GetFloatNamedOrPosArgDefault(k string, n int, v float64) (float64, error) {
   417  	if a := e.getNamedArg(k); a != nil {
   418  		return a.doGetFloatArg()
   419  	}
   420  
   421  	return e.GetFloatArgDefault(n, v)
   422  }
   423  
   424  func (e *expr) GetIntArg(n int) (int, error) {
   425  	if len(e.args) <= n {
   426  		return 0, ErrMissingArgument
   427  	}
   428  
   429  	return e.args[n].doGetIntArg()
   430  }
   431  
   432  func (e *expr) GetIntArgs(n int) ([]int, error) {
   433  	if len(e.args) < n {
   434  		return nil, ErrMissingArgument
   435  	}
   436  
   437  	ints := make([]int, 0, len(e.args)-n)
   438  
   439  	for i := n; i < len(e.args); i++ {
   440  		a, err := e.GetIntArg(i)
   441  		if err != nil {
   442  			return nil, err
   443  		}
   444  		ints = append(ints, a)
   445  	}
   446  
   447  	return ints, nil
   448  }
   449  
   450  func (e *expr) GetIntArgDefault(n, d int) (int, error) {
   451  	if len(e.args) <= n {
   452  		return d, nil
   453  	}
   454  
   455  	return e.args[n].doGetIntArg()
   456  }
   457  
   458  func (e *expr) GetIntArgWithIndication(n int) (int, bool, error) {
   459  	if len(e.args) <= n {
   460  		return 0, false, nil
   461  	}
   462  
   463  	v, err := e.args[n].doGetIntArg()
   464  	return v, true, err
   465  }
   466  
   467  func (e *expr) GetIntNamedOrPosArgWithIndication(k string, n int) (int, bool, error) {
   468  	if a := e.getNamedArg(k); a != nil {
   469  		v, err := a.doGetIntArg()
   470  		return v, true, err
   471  	}
   472  
   473  	return e.GetIntArgWithIndication(n)
   474  }
   475  
   476  func (e *expr) GetIntNamedOrPosArgDefault(k string, n, d int) (int, error) {
   477  	if a := e.getNamedArg(k); a != nil {
   478  		return a.doGetIntArg()
   479  	}
   480  
   481  	return e.GetIntArgDefault(n, d)
   482  }
   483  
   484  func (e *expr) GetIntOrInfArg(n int) (IntOrInf, error) {
   485  	if len(e.args) <= n {
   486  		return IntOrInf{}, ErrMissingArgument
   487  	}
   488  
   489  	return e.args[n].doGetIntOrInfArg()
   490  }
   491  
   492  func (e *expr) GetIntOrInfArgDefault(n int, d IntOrInf) (IntOrInf, error) {
   493  	if len(e.args) <= n {
   494  		return d, nil
   495  	}
   496  
   497  	return e.args[n].doGetIntOrInfArg()
   498  }
   499  
   500  func (e *expr) GetIntOrInfNamedOrPosArgDefault(k string, n int, d IntOrInf) (IntOrInf, error) {
   501  	if a := e.getNamedArg(k); a != nil {
   502  		return a.doGetIntOrInfArg()
   503  	}
   504  
   505  	return e.GetIntOrInfArgDefault(n, d)
   506  }
   507  
   508  func (e *expr) GetNamedArg(name string) Expr {
   509  	return e.getNamedArg(name)
   510  }
   511  
   512  func (e *expr) GetBoolNamedOrPosArgDefault(k string, n int, b bool) (bool, error) {
   513  	if a := e.getNamedArg(k); a != nil {
   514  		return a.doGetBoolArg()
   515  	}
   516  
   517  	return e.GetBoolArgDefault(n, b)
   518  }
   519  
   520  func (e *expr) GetBoolArgDefault(n int, b bool) (bool, error) {
   521  	if len(e.args) <= n {
   522  		return b, nil
   523  	}
   524  
   525  	return e.args[n].doGetBoolArg()
   526  }
   527  
   528  func (e *expr) GetNodeOrTagArgs(n int, single bool) ([]NodeOrTag, error) {
   529  	// if single==false, zero nodes is OK
   530  	if single && len(e.args) <= n || len(e.args) < n {
   531  		return nil, ErrMissingArgument
   532  	}
   533  
   534  	nodeTags := make([]NodeOrTag, 0, len(e.args)-n)
   535  
   536  	var err error
   537  	until := len(e.args)
   538  	if single {
   539  		until = n + 1
   540  	}
   541  	for i := n; i < until; i++ {
   542  		var nodeTag NodeOrTag
   543  		nodeTag.Value, err = e.GetIntArg(i)
   544  		if err != nil {
   545  			// Try to parse it as String
   546  			nodeTag.Value, err = e.GetStringArg(i)
   547  			if err != nil {
   548  				return nil, err
   549  			}
   550  			nodeTag.IsTag = true
   551  		}
   552  		nodeTags = append(nodeTags, nodeTag)
   553  	}
   554  
   555  	return nodeTags, nil
   556  }
   557  
   558  func (e *expr) IsInterfaceNil() bool {
   559  	return e == nil
   560  }
   561  
   562  func (e *expr) insertFirstArg(exp *expr) error {
   563  	if e.etype != EtFunc {
   564  		return fmt.Errorf("pipe to not a function")
   565  	}
   566  
   567  	newArgs := []*expr{exp}
   568  	e.args = append(newArgs, e.args...)
   569  
   570  	if e.argString == "" {
   571  		e.argString = exp.ToString()
   572  	} else {
   573  		e.argString = exp.ToString() + "," + e.argString
   574  	}
   575  
   576  	return nil
   577  }
   578  
   579  func skipWhitespace(e string) string {
   580  	skipTo := len(e)
   581  	for i, r := range e {
   582  		if !unicode.IsSpace(r) {
   583  			skipTo = i
   584  			break
   585  		}
   586  	}
   587  	return e[skipTo:]
   588  }
   589  
   590  func parseExprWithoutPipe(e string) (Expr, string, error) {
   591  	e = skipWhitespace(e)
   592  
   593  	if e == "" {
   594  		return nil, "", ErrMissingExpr
   595  	}
   596  
   597  	if '0' <= e[0] && e[0] <= '9' || e[0] == '-' || e[0] == '+' {
   598  		val, valStr, e, err := parseConst(e)
   599  		r, _ := utf8.DecodeRuneInString(e)
   600  		if !unicode.IsLetter(r) {
   601  			return &expr{val: val, etype: EtConst, valStr: valStr}, e, err
   602  		}
   603  	}
   604  
   605  	if e[0] == '\'' || e[0] == '"' {
   606  		val, e, err := parseString(e)
   607  		return &expr{valStr: val, etype: EtString}, e, err
   608  	}
   609  
   610  	name, e := parseName(e)
   611  
   612  	if name == "" {
   613  		return nil, e, ErrMissingArgument
   614  	}
   615  
   616  	nameLower := strings.ToLower(name)
   617  	if nameLower == "false" || nameLower == "true" {
   618  		return &expr{valStr: nameLower, etype: EtBool, target: nameLower}, e, nil
   619  	}
   620  
   621  	if e != "" && e[0] == '(' {
   622  		// TODO(civil): Tags: make it a proper Expression
   623  		if name == "seriesByTag" {
   624  			argString, _, _, e, err := parseArgList(e)
   625  			return &expr{target: name + "(" + argString + ")", etype: EtName}, e, err
   626  		}
   627  		exp := &expr{target: name, etype: EtFunc}
   628  
   629  		argString, posArgs, namedArgs, e, err := parseArgList(e)
   630  		exp.argString = argString
   631  		exp.args = posArgs
   632  		exp.namedArgs = namedArgs
   633  
   634  		return exp, e, err
   635  	}
   636  
   637  	return &expr{target: name}, e, nil
   638  }
   639  
   640  func parseExprInner(e string) (Expr, string, error) {
   641  	exp, e, err := parseExprWithoutPipe(e)
   642  	if err != nil {
   643  		return exp, e, err
   644  	}
   645  	return pipe(exp.(*expr), e)
   646  }
   647  
   648  // ParseExpr actually do all the parsing. It returns expression, original string and error (if any)
   649  func ParseExpr(e string) (Expr, string, error) {
   650  	exp, e, err := parseExprInner(e)
   651  	if err != nil {
   652  		return exp, e, err
   653  	}
   654  	exp, err = defineMap.expandExpr(exp.(*expr))
   655  	return exp, e, err
   656  }
   657  
   658  func pipe(exp *expr, e string) (*expr, string, error) {
   659  	e = skipWhitespace(e)
   660  
   661  	if e == "" || e[0] != '|' {
   662  		return exp, e, nil
   663  	}
   664  
   665  	wr, e, err := parseExprWithoutPipe(e[1:])
   666  	if err != nil {
   667  		return exp, e, err
   668  	}
   669  	if wr == nil {
   670  		return exp, e, nil
   671  	}
   672  
   673  	err = wr.(*expr).insertFirstArg(exp)
   674  	if err != nil {
   675  		return exp, e, err
   676  	}
   677  	exp = wr.(*expr)
   678  
   679  	return pipe(exp, e)
   680  }
   681  
   682  // IsNameChar checks if specified char is actually a valid (from graphite's protocol point of view)
   683  func IsNameChar(r byte) bool {
   684  	return false ||
   685  		'a' <= r && r <= 'z' ||
   686  		'A' <= r && r <= 'Z' ||
   687  		'0' <= r && r <= '9' ||
   688  		r == '.' || r == '_' ||
   689  		r == '-' || r == '*' ||
   690  		r == '?' || r == ':' ||
   691  		r == '[' || r == ']' ||
   692  		r == '^' || r == '$' ||
   693  		r == '<' || r == '>' ||
   694  		r == '&' || r == '#' ||
   695  		r == '/' || r == '%' ||
   696  		r == '@'
   697  }
   698  
   699  func IsDigit(r byte) bool {
   700  	return '0' <= r && r <= '9'
   701  }
   702  
   703  func parseArgList(e string) (string, []*expr, map[string]*expr, string, error) {
   704  	var (
   705  		posArgs   []*expr
   706  		namedArgs map[string]*expr
   707  	)
   708  	eOrig := e
   709  
   710  	if e[0] != '(' {
   711  		panic("arg list should start with paren")
   712  	}
   713  
   714  	var argStringBuffer bytes.Buffer
   715  
   716  	e = e[1:]
   717  
   718  	// check for empty args
   719  	t := skipWhitespace(e)
   720  	if t != "" && t[0] == ')' {
   721  		return "", posArgs, namedArgs, t[1:], nil
   722  	}
   723  
   724  	charNum := 1
   725  	for {
   726  		var arg Expr
   727  		var err error
   728  		charNum++
   729  
   730  		argString := e
   731  		arg, e, err = parseExprInner(e)
   732  		if err != nil {
   733  			return "", nil, nil, e, err
   734  		}
   735  
   736  		if e == "" {
   737  			return "", nil, nil, "", ErrMissingComma
   738  		}
   739  
   740  		// we now know we're parsing a key-value pair
   741  		if arg.IsName() && e[0] == '=' {
   742  			e = e[1:]
   743  			argCont, eCont, errCont := parseExprInner(e)
   744  			if errCont != nil {
   745  				return "", nil, nil, eCont, errCont
   746  			}
   747  
   748  			if eCont == "" {
   749  				return "", nil, nil, "", ErrMissingComma
   750  			}
   751  
   752  			if !argCont.IsConst() && !argCont.IsName() && !argCont.IsString() && !argCont.IsBool() {
   753  				return "", nil, nil, eCont, ErrBadType
   754  			}
   755  
   756  			if namedArgs == nil {
   757  				namedArgs = make(map[string]*expr)
   758  			}
   759  
   760  			exp := &expr{
   761  				etype:  argCont.Type(),
   762  				val:    argCont.FloatValue(),
   763  				valStr: argCont.StringValue(),
   764  				target: argCont.Target(),
   765  			}
   766  			namedArgs[arg.Target()] = exp
   767  
   768  			e = eCont
   769  			if argStringBuffer.Len() > 0 {
   770  				argStringBuffer.WriteByte(',')
   771  			}
   772  			argStringBuffer.WriteString(argString[:len(argString)-len(e)])
   773  			charNum += len(argString) - len(e)
   774  		} else {
   775  			exp := arg.toExpr().(*expr)
   776  			posArgs = append(posArgs, exp)
   777  
   778  			if argStringBuffer.Len() > 0 {
   779  				argStringBuffer.WriteByte(',')
   780  			}
   781  			if exp.IsFunc() {
   782  				expString := exp.ToString()
   783  				argStringBuffer.WriteString(expString)
   784  				charNum += len(expString)
   785  			} else {
   786  				argStringBuffer.WriteString(argString[:len(argString)-len(e)])
   787  				charNum += len(argString) - len(e)
   788  			}
   789  		}
   790  
   791  		// after the argument, trim any trailing spaces
   792  		e = skipWhitespace(e)
   793  
   794  		if e[0] == ')' {
   795  			return argStringBuffer.String(), posArgs, namedArgs, e[1:], nil
   796  		}
   797  
   798  		if e[0] != ',' && e[0] != ' ' {
   799  			return "", nil, nil, "", merry.Wrap(ErrUnexpectedCharacter).WithUserMessagef("string_to_parse=`%v`, character_number=%v, character=`%v`", eOrig, charNum, string(e[0]))
   800  		}
   801  
   802  		e = e[1:]
   803  	}
   804  }
   805  
   806  func parseConst(s string) (float64, string, string, error) {
   807  	var i int
   808  	// All valid characters for a floating-point constant
   809  	// Just slurp them all in and let ParseFloat sort 'em out
   810  	for i < len(s) && (IsDigit(s[i]) || s[i] == '.' || s[i] == '+' || s[i] == '-' || s[i] == 'e' || s[i] == 'E') {
   811  		i++
   812  	}
   813  
   814  	v, err := strconv.ParseFloat(s[:i], 64)
   815  	if err != nil {
   816  		return 0, "", "", err
   817  	}
   818  
   819  	return v, s[:i], s[i:], err
   820  }
   821  
   822  // RangeTables is an array of *unicode.RangeTable
   823  var RangeTables []*unicode.RangeTable
   824  
   825  var disallowedCharactersInMetricName = map[rune]struct{}{
   826  	'(':  struct{}{},
   827  	')':  struct{}{},
   828  	'"':  struct{}{},
   829  	'\'': struct{}{},
   830  	' ':  struct{}{},
   831  	'/':  struct{}{},
   832  }
   833  
   834  func unicodeRuneAllowedInName(r rune) bool {
   835  	if _, ok := disallowedCharactersInMetricName[r]; ok {
   836  		return false
   837  	}
   838  
   839  	return true
   840  }
   841  
   842  func parseName(s string) (string, string) {
   843  	var (
   844  		braces, i, w int
   845  		r            rune
   846  		isEscape     bool
   847  		isDefault    bool
   848  	)
   849  
   850  	buf := bytes.NewBuffer(make([]byte, 0, len(s)))
   851  
   852  FOR:
   853  	for braces, i, w = 0, 0, 0; i < len(s); i += w {
   854  		if s[i] != '\\' {
   855  			err := buf.WriteByte(s[i])
   856  			if err != nil {
   857  				break FOR
   858  			}
   859  		}
   860  		isDefault = false
   861  		w = 1
   862  		if IsNameChar(s[i]) {
   863  			continue
   864  		}
   865  
   866  		switch s[i] {
   867  		case '\\':
   868  			if isEscape {
   869  				err := buf.WriteByte(s[i])
   870  				if err != nil {
   871  					break FOR
   872  				}
   873  				isEscape = false
   874  				continue
   875  			}
   876  			isEscape = true
   877  		case '{':
   878  			if isEscape {
   879  				isDefault = true
   880  			} else {
   881  				braces++
   882  			}
   883  		case '}':
   884  			if isEscape {
   885  				isDefault = true
   886  			} else {
   887  				if braces == 0 {
   888  					break FOR
   889  				}
   890  				braces--
   891  			}
   892  		case ',':
   893  			if isEscape {
   894  				isDefault = true
   895  			} else if braces == 0 {
   896  				break FOR
   897  			}
   898  		/* */
   899  		case '=':
   900  			// allow metric name to end with any amount of `=` without treating it as a named arg or tag
   901  			if !isEscape {
   902  				if len(s) < i+2 || s[i+1] == '=' || s[i+1] == ',' || s[i+1] == ')' {
   903  					continue
   904  				}
   905  			}
   906  			fallthrough
   907  		/* */
   908  		default:
   909  			isDefault = true
   910  		}
   911  		if isDefault {
   912  			r, w = utf8.DecodeRuneInString(s[i:])
   913  			if unicodeRuneAllowedInName(r) && unicode.In(r, RangeTables...) {
   914  				continue
   915  			}
   916  			if !isEscape {
   917  				break FOR
   918  			}
   919  			isEscape = false
   920  			continue
   921  		}
   922  	}
   923  
   924  	if i == len(s) {
   925  		return buf.String(), ""
   926  	}
   927  
   928  	return s[:i], s[i:]
   929  }
   930  
   931  func parseString(s string) (string, string, error) {
   932  	if s[0] != '\'' && s[0] != '"' {
   933  		panic("string should start with open quote")
   934  	}
   935  
   936  	match := s[0]
   937  
   938  	s = s[1:]
   939  
   940  	var i int
   941  	for i < len(s) && s[i] != match {
   942  		i++
   943  	}
   944  
   945  	if i == len(s) {
   946  		return "", "", ErrMissingQuote
   947  
   948  	}
   949  
   950  	return s[:i], s[i+1:], nil
   951  }
   952  
   953  func StartAlignTo(start int64, alignTo string) (int64, error) {
   954  	var newDate time.Time
   955  	re := regexp.MustCompile(`^[0-9]+`)
   956  	alignTo = re.ReplaceAllString(alignTo, "")
   957  
   958  	startDate := time.Unix(start, 0).UTC()
   959  	switch {
   960  	case strings.HasPrefix(alignTo, "y"):
   961  		newDate = time.Date(startDate.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
   962  	case strings.HasPrefix(alignTo, "mon"):
   963  		newDate = time.Date(startDate.Year(), startDate.Month(), 1, 0, 0, 0, 0, time.UTC)
   964  	case strings.HasPrefix(alignTo, "w"):
   965  		if !IsDigit(alignTo[len(alignTo)-1]) {
   966  			return start, ErrInvalidInterval
   967  		}
   968  		newDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), 0, 0, 0, 0, time.UTC)
   969  		dayOfWeek, err := strconv.Atoi(alignTo[len(alignTo)-1:])
   970  		if err != nil {
   971  			return start, ErrInvalidInterval
   972  		}
   973  
   974  		startDayOfWeek := int(startDate.Weekday())
   975  		daysToSubtract := startDayOfWeek - dayOfWeek
   976  		if daysToSubtract < 0 {
   977  			daysToSubtract += 7
   978  		}
   979  		newDate = newDate.AddDate(0, 0, -daysToSubtract)
   980  	case strings.HasPrefix(alignTo, "d"):
   981  		newDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), 0, 0, 0, 0, time.UTC)
   982  	case strings.HasPrefix(alignTo, "h"):
   983  		newDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), startDate.Hour(), 0, 0, 0, time.UTC)
   984  	case strings.HasPrefix(alignTo, "min"):
   985  		newDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), startDate.Hour(), startDate.Minute(), 0, 0, time.UTC)
   986  	case strings.HasPrefix(alignTo, "s"):
   987  		newDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), startDate.Hour(), startDate.Minute(), startDate.Second(), 0, time.UTC)
   988  	default:
   989  		return start, ErrInvalidInterval
   990  	}
   991  	return newDate.Unix(), nil
   992  }