...

Source file src/github.com/PaesslerAG/gval/parse.go

Documentation: github.com/PaesslerAG/gval

     1  package gval
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  	"text/scanner"
     9  
    10  	"github.com/shopspring/decimal"
    11  )
    12  
    13  //ParseExpression scans an expression into an Evaluable.
    14  func (p *Parser) ParseExpression(c context.Context) (eval Evaluable, err error) {
    15  	stack := stageStack{}
    16  	for {
    17  		eval, err = p.ParseNextExpression(c)
    18  		if err != nil {
    19  			return nil, err
    20  		}
    21  
    22  		if stage, err := p.parseOperator(c, &stack, eval); err != nil {
    23  			return nil, err
    24  		} else if err = stack.push(stage); err != nil {
    25  			return nil, err
    26  		}
    27  
    28  		if stack.peek().infixBuilder == nil {
    29  			return stack.pop().Evaluable, nil
    30  		}
    31  	}
    32  }
    33  
    34  //ParseNextExpression scans the expression ignoring following operators
    35  func (p *Parser) ParseNextExpression(c context.Context) (eval Evaluable, err error) {
    36  	scan := p.Scan()
    37  	ex, ok := p.prefixes[scan]
    38  	if !ok {
    39  		if scan != scanner.EOF && p.def != nil {
    40  			return p.def(c, p)
    41  		}
    42  		return nil, p.Expected("extensions")
    43  	}
    44  	return ex(c, p)
    45  }
    46  
    47  // ParseSublanguage sets the next language for this parser to parse and calls
    48  // its initialization function, usually ParseExpression.
    49  func (p *Parser) ParseSublanguage(c context.Context, l Language) (Evaluable, error) {
    50  	if p.isCamouflaged() {
    51  		panic("can not ParseSublanguage() on camouflaged Parser")
    52  	}
    53  	curLang := p.Language
    54  	curWhitespace := p.scanner.Whitespace
    55  	curMode := p.scanner.Mode
    56  	curIsIdentRune := p.scanner.IsIdentRune
    57  
    58  	p.Language = l
    59  	p.resetScannerProperties()
    60  
    61  	defer func() {
    62  		p.Language = curLang
    63  		p.scanner.Whitespace = curWhitespace
    64  		p.scanner.Mode = curMode
    65  		p.scanner.IsIdentRune = curIsIdentRune
    66  	}()
    67  
    68  	return p.parse(c)
    69  }
    70  
    71  func (p *Parser) parse(c context.Context) (Evaluable, error) {
    72  	if p.init != nil {
    73  		return p.init(c, p)
    74  	}
    75  
    76  	return p.ParseExpression(c)
    77  }
    78  
    79  func parseString(c context.Context, p *Parser) (Evaluable, error) {
    80  	s, err := strconv.Unquote(p.TokenText())
    81  	if err != nil {
    82  		return nil, fmt.Errorf("could not parse string: %w", err)
    83  	}
    84  	return p.Const(s), nil
    85  }
    86  
    87  func parseNumber(c context.Context, p *Parser) (Evaluable, error) {
    88  	n, err := strconv.ParseFloat(p.TokenText(), 64)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	return p.Const(n), nil
    93  }
    94  
    95  func parseDecimal(c context.Context, p *Parser) (Evaluable, error) {
    96  	n, err := strconv.ParseFloat(p.TokenText(), 64)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	return p.Const(decimal.NewFromFloat(n)), nil
   101  }
   102  
   103  func parseParentheses(c context.Context, p *Parser) (Evaluable, error) {
   104  	eval, err := p.ParseExpression(c)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	switch p.Scan() {
   109  	case ')':
   110  		return eval, nil
   111  	default:
   112  		return nil, p.Expected("parentheses", ')')
   113  	}
   114  }
   115  
   116  func (p *Parser) parseOperator(c context.Context, stack *stageStack, eval Evaluable) (st stage, err error) {
   117  	for {
   118  		scan := p.Scan()
   119  		op := p.TokenText()
   120  		mustOp := false
   121  		if p.isSymbolOperation(scan) {
   122  			scan = p.Peek()
   123  			for p.isSymbolOperation(scan) && p.isOperatorPrefix(op+string(scan)) {
   124  				mustOp = true
   125  				op += string(scan)
   126  				p.Next()
   127  				scan = p.Peek()
   128  			}
   129  		} else if scan != scanner.Ident {
   130  			p.Camouflage("operator")
   131  			return stage{Evaluable: eval}, nil
   132  		}
   133  		switch operator := p.operators[op].(type) {
   134  		case *infix:
   135  			return stage{
   136  				Evaluable:          eval,
   137  				infixBuilder:       operator.builder,
   138  				operatorPrecedence: operator.operatorPrecedence,
   139  			}, nil
   140  		case directInfix:
   141  			return stage{
   142  				Evaluable:          eval,
   143  				infixBuilder:       operator.infixBuilder,
   144  				operatorPrecedence: operator.operatorPrecedence,
   145  			}, nil
   146  		case postfix:
   147  			if err = stack.push(stage{
   148  				operatorPrecedence: operator.operatorPrecedence,
   149  				Evaluable:          eval,
   150  			}); err != nil {
   151  				return stage{}, err
   152  			}
   153  			eval, err = operator.f(c, p, stack.pop().Evaluable, operator.operatorPrecedence)
   154  			if err != nil {
   155  				return
   156  			}
   157  			continue
   158  		}
   159  
   160  		if !mustOp {
   161  			p.Camouflage("operator")
   162  			return stage{Evaluable: eval}, nil
   163  		}
   164  		return stage{}, fmt.Errorf("unknown operator %s", op)
   165  	}
   166  }
   167  
   168  func parseIdent(c context.Context, p *Parser) (call string, alternative func() (Evaluable, error), err error) {
   169  	token := p.TokenText()
   170  	return token,
   171  		func() (Evaluable, error) {
   172  			fullname := token
   173  
   174  			keys := []Evaluable{p.Const(token)}
   175  			for {
   176  				scan := p.Scan()
   177  				switch scan {
   178  				case '.':
   179  					scan = p.Scan()
   180  					switch scan {
   181  					case scanner.Ident:
   182  						token = p.TokenText()
   183  						keys = append(keys, p.Const(token))
   184  					default:
   185  						return nil, p.Expected("field", scanner.Ident)
   186  					}
   187  				case '(':
   188  					args, err := p.parseArguments(c)
   189  					if err != nil {
   190  						return nil, err
   191  					}
   192  					return p.callEvaluable(fullname, p.Var(keys...), args...), nil
   193  				case '[':
   194  					key, err := p.ParseExpression(c)
   195  					if err != nil {
   196  						return nil, err
   197  					}
   198  					switch p.Scan() {
   199  					case ']':
   200  						keys = append(keys, key)
   201  					default:
   202  						return nil, p.Expected("array key", ']')
   203  					}
   204  				default:
   205  					p.Camouflage("variable", '.', '(', '[')
   206  					return p.Var(keys...), nil
   207  				}
   208  			}
   209  		}, nil
   210  
   211  }
   212  
   213  func (p *Parser) parseArguments(c context.Context) (args []Evaluable, err error) {
   214  	if p.Scan() == ')' {
   215  		return
   216  	}
   217  	p.Camouflage("scan arguments", ')')
   218  	for {
   219  		arg, err := p.ParseExpression(c)
   220  		args = append(args, arg)
   221  		if err != nil {
   222  			return nil, err
   223  		}
   224  		switch p.Scan() {
   225  		case ')':
   226  			return args, nil
   227  		case ',':
   228  		default:
   229  			return nil, p.Expected("arguments", ')', ',')
   230  		}
   231  	}
   232  }
   233  
   234  func inArray(a, b interface{}) (interface{}, error) {
   235  	col, ok := b.([]interface{})
   236  	if !ok {
   237  		return nil, fmt.Errorf("expected type []interface{} for in operator but got %T", b)
   238  	}
   239  	for _, value := range col {
   240  		if reflect.DeepEqual(a, value) {
   241  			return true, nil
   242  		}
   243  	}
   244  	return false, nil
   245  }
   246  
   247  func parseIf(c context.Context, p *Parser, e Evaluable) (Evaluable, error) {
   248  	a, err := p.ParseExpression(c)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  	b := p.Const(nil)
   253  	switch p.Scan() {
   254  	case ':':
   255  		b, err = p.ParseExpression(c)
   256  		if err != nil {
   257  			return nil, err
   258  		}
   259  	case scanner.EOF:
   260  	default:
   261  		return nil, p.Expected("<> ? <> : <>", ':', scanner.EOF)
   262  	}
   263  	return func(c context.Context, v interface{}) (interface{}, error) {
   264  		x, err := e(c, v)
   265  		if err != nil {
   266  			return nil, err
   267  		}
   268  		if valX := reflect.ValueOf(x); x == nil || valX.IsZero() {
   269  			return b(c, v)
   270  		}
   271  		return a(c, v)
   272  	}, nil
   273  }
   274  
   275  func parseJSONArray(c context.Context, p *Parser) (Evaluable, error) {
   276  	evals := []Evaluable{}
   277  	for {
   278  		switch p.Scan() {
   279  		default:
   280  			p.Camouflage("array", ',', ']')
   281  			eval, err := p.ParseExpression(c)
   282  			if err != nil {
   283  				return nil, err
   284  			}
   285  			evals = append(evals, eval)
   286  		case ',':
   287  		case ']':
   288  			return func(c context.Context, v interface{}) (interface{}, error) {
   289  				vs := make([]interface{}, len(evals))
   290  				for i, e := range evals {
   291  					eval, err := e(c, v)
   292  					if err != nil {
   293  						return nil, err
   294  					}
   295  					vs[i] = eval
   296  				}
   297  
   298  				return vs, nil
   299  			}, nil
   300  		}
   301  	}
   302  }
   303  
   304  func parseJSONObject(c context.Context, p *Parser) (Evaluable, error) {
   305  	type kv struct {
   306  		key   Evaluable
   307  		value Evaluable
   308  	}
   309  	evals := []kv{}
   310  	for {
   311  		switch p.Scan() {
   312  		default:
   313  			p.Camouflage("object", ',', '}')
   314  			key, err := p.ParseExpression(c)
   315  			if err != nil {
   316  				return nil, err
   317  			}
   318  			if p.Scan() != ':' {
   319  				if err != nil {
   320  					return nil, p.Expected("object", ':')
   321  				}
   322  			}
   323  			value, err := p.ParseExpression(c)
   324  			if err != nil {
   325  				return nil, err
   326  			}
   327  			evals = append(evals, kv{key, value})
   328  		case ',':
   329  		case '}':
   330  			return func(c context.Context, v interface{}) (interface{}, error) {
   331  				vs := map[string]interface{}{}
   332  				for _, e := range evals {
   333  					value, err := e.value(c, v)
   334  					if err != nil {
   335  						return nil, err
   336  					}
   337  					key, err := e.key.EvalString(c, v)
   338  					if err != nil {
   339  						return nil, err
   340  					}
   341  					vs[key] = value
   342  				}
   343  				return vs, nil
   344  			}, nil
   345  		}
   346  	}
   347  }
   348  

View as plain text