github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/flosch/pongo2.v3/parser_expression.go (about)

     1  package pongo2
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math"
     7  )
     8  
     9  type Expression struct {
    10  	// TODO: Add location token?
    11  	expr1    IEvaluator
    12  	expr2    IEvaluator
    13  	op_token *Token
    14  }
    15  
    16  type relationalExpression struct {
    17  	// TODO: Add location token?
    18  	expr1    IEvaluator
    19  	expr2    IEvaluator
    20  	op_token *Token
    21  }
    22  
    23  type simpleExpression struct {
    24  	negate        bool
    25  	negative_sign bool
    26  	term1         IEvaluator
    27  	term2         IEvaluator
    28  	op_token      *Token
    29  }
    30  
    31  type term struct {
    32  	// TODO: Add location token?
    33  	factor1  IEvaluator
    34  	factor2  IEvaluator
    35  	op_token *Token
    36  }
    37  
    38  type power struct {
    39  	// TODO: Add location token?
    40  	power1 IEvaluator
    41  	power2 IEvaluator
    42  }
    43  
    44  func (expr *Expression) FilterApplied(name string) bool {
    45  	return expr.expr1.FilterApplied(name) && (expr.expr2 == nil ||
    46  		(expr.expr2 != nil && expr.expr2.FilterApplied(name)))
    47  }
    48  
    49  func (expr *relationalExpression) FilterApplied(name string) bool {
    50  	return expr.expr1.FilterApplied(name) && (expr.expr2 == nil ||
    51  		(expr.expr2 != nil && expr.expr2.FilterApplied(name)))
    52  }
    53  
    54  func (expr *simpleExpression) FilterApplied(name string) bool {
    55  	return expr.term1.FilterApplied(name) && (expr.term2 == nil ||
    56  		(expr.term2 != nil && expr.term2.FilterApplied(name)))
    57  }
    58  
    59  func (t *term) FilterApplied(name string) bool {
    60  	return t.factor1.FilterApplied(name) && (t.factor2 == nil ||
    61  		(t.factor2 != nil && t.factor2.FilterApplied(name)))
    62  }
    63  
    64  func (p *power) FilterApplied(name string) bool {
    65  	return p.power1.FilterApplied(name) && (p.power2 == nil ||
    66  		(p.power2 != nil && p.power2.FilterApplied(name)))
    67  }
    68  
    69  func (expr *Expression) GetPositionToken() *Token {
    70  	return expr.expr1.GetPositionToken()
    71  }
    72  
    73  func (expr *relationalExpression) GetPositionToken() *Token {
    74  	return expr.expr1.GetPositionToken()
    75  }
    76  
    77  func (expr *simpleExpression) GetPositionToken() *Token {
    78  	return expr.term1.GetPositionToken()
    79  }
    80  
    81  func (expr *term) GetPositionToken() *Token {
    82  	return expr.factor1.GetPositionToken()
    83  }
    84  
    85  func (expr *power) GetPositionToken() *Token {
    86  	return expr.power1.GetPositionToken()
    87  }
    88  
    89  func (expr *Expression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
    90  	value, err := expr.Evaluate(ctx)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	buffer.WriteString(value.String())
    95  	return nil
    96  }
    97  
    98  func (expr *relationalExpression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
    99  	value, err := expr.Evaluate(ctx)
   100  	if err != nil {
   101  		return err
   102  	}
   103  	buffer.WriteString(value.String())
   104  	return nil
   105  }
   106  
   107  func (expr *simpleExpression) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
   108  	value, err := expr.Evaluate(ctx)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	buffer.WriteString(value.String())
   113  	return nil
   114  }
   115  
   116  func (expr *term) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
   117  	value, err := expr.Evaluate(ctx)
   118  	if err != nil {
   119  		return err
   120  	}
   121  	buffer.WriteString(value.String())
   122  	return nil
   123  }
   124  
   125  func (expr *power) Execute(ctx *ExecutionContext, buffer *bytes.Buffer) *Error {
   126  	value, err := expr.Evaluate(ctx)
   127  	if err != nil {
   128  		return err
   129  	}
   130  	buffer.WriteString(value.String())
   131  	return nil
   132  }
   133  
   134  func (expr *Expression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
   135  	v1, err := expr.expr1.Evaluate(ctx)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	if expr.expr2 != nil {
   140  		v2, err := expr.expr2.Evaluate(ctx)
   141  		if err != nil {
   142  			return nil, err
   143  		}
   144  		switch expr.op_token.Val {
   145  		case "and", "&&":
   146  			return AsValue(v1.IsTrue() && v2.IsTrue()), nil
   147  		case "or", "||":
   148  			return AsValue(v1.IsTrue() || v2.IsTrue()), nil
   149  		default:
   150  			panic(fmt.Sprintf("unimplemented: %s", expr.op_token.Val))
   151  		}
   152  	} else {
   153  		return v1, nil
   154  	}
   155  }
   156  
   157  func (expr *relationalExpression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
   158  	v1, err := expr.expr1.Evaluate(ctx)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  	if expr.expr2 != nil {
   163  		v2, err := expr.expr2.Evaluate(ctx)
   164  		if err != nil {
   165  			return nil, err
   166  		}
   167  		switch expr.op_token.Val {
   168  		case "<=":
   169  			if v1.IsFloat() || v2.IsFloat() {
   170  				return AsValue(v1.Float() <= v2.Float()), nil
   171  			} else {
   172  				return AsValue(v1.Integer() <= v2.Integer()), nil
   173  			}
   174  		case ">=":
   175  			if v1.IsFloat() || v2.IsFloat() {
   176  				return AsValue(v1.Float() >= v2.Float()), nil
   177  			} else {
   178  				return AsValue(v1.Integer() >= v2.Integer()), nil
   179  			}
   180  		case "==":
   181  			return AsValue(v1.EqualValueTo(v2)), nil
   182  		case ">":
   183  			if v1.IsFloat() || v2.IsFloat() {
   184  				return AsValue(v1.Float() > v2.Float()), nil
   185  			} else {
   186  				return AsValue(v1.Integer() > v2.Integer()), nil
   187  			}
   188  		case "<":
   189  			if v1.IsFloat() || v2.IsFloat() {
   190  				return AsValue(v1.Float() < v2.Float()), nil
   191  			} else {
   192  				return AsValue(v1.Integer() < v2.Integer()), nil
   193  			}
   194  		case "!=", "<>":
   195  			return AsValue(!v1.EqualValueTo(v2)), nil
   196  		case "in":
   197  			return AsValue(v2.Contains(v1)), nil
   198  		default:
   199  			panic(fmt.Sprintf("unimplemented: %s", expr.op_token.Val))
   200  		}
   201  	} else {
   202  		return v1, nil
   203  	}
   204  }
   205  
   206  func (expr *simpleExpression) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
   207  	t1, err := expr.term1.Evaluate(ctx)
   208  	if err != nil {
   209  		return nil, err
   210  	}
   211  	result := t1
   212  
   213  	if expr.negate {
   214  		result = result.Negate()
   215  	}
   216  
   217  	if expr.negative_sign {
   218  		if result.IsNumber() {
   219  			switch {
   220  			case result.IsFloat():
   221  				result = AsValue(-1 * result.Float())
   222  			case result.IsInteger():
   223  				result = AsValue(-1 * result.Integer())
   224  			default:
   225  				panic("not possible")
   226  			}
   227  		} else {
   228  			return nil, ctx.Error("Negative sign on a non-number expression", expr.GetPositionToken())
   229  		}
   230  	}
   231  
   232  	if expr.term2 != nil {
   233  		t2, err := expr.term2.Evaluate(ctx)
   234  		if err != nil {
   235  			return nil, err
   236  		}
   237  		switch expr.op_token.Val {
   238  		case "+":
   239  			if result.IsFloat() || t2.IsFloat() {
   240  				// Result will be a float
   241  				return AsValue(result.Float() + t2.Float()), nil
   242  			} else {
   243  				// Result will be an integer
   244  				return AsValue(result.Integer() + t2.Integer()), nil
   245  			}
   246  		case "-":
   247  			if result.IsFloat() || t2.IsFloat() {
   248  				// Result will be a float
   249  				return AsValue(result.Float() - t2.Float()), nil
   250  			} else {
   251  				// Result will be an integer
   252  				return AsValue(result.Integer() - t2.Integer()), nil
   253  			}
   254  		default:
   255  			panic("unimplemented")
   256  		}
   257  	}
   258  
   259  	return result, nil
   260  }
   261  
   262  func (t *term) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
   263  	f1, err := t.factor1.Evaluate(ctx)
   264  	if err != nil {
   265  		return nil, err
   266  	}
   267  	if t.factor2 != nil {
   268  		f2, err := t.factor2.Evaluate(ctx)
   269  		if err != nil {
   270  			return nil, err
   271  		}
   272  		switch t.op_token.Val {
   273  		case "*":
   274  			if f1.IsFloat() || f2.IsFloat() {
   275  				// Result will be float
   276  				return AsValue(f1.Float() * f2.Float()), nil
   277  			}
   278  			// Result will be int
   279  			return AsValue(f1.Integer() * f2.Integer()), nil
   280  		case "/":
   281  			if f1.IsFloat() || f2.IsFloat() {
   282  				// Result will be float
   283  				return AsValue(f1.Float() / f2.Float()), nil
   284  			}
   285  			// Result will be int
   286  			return AsValue(f1.Integer() / f2.Integer()), nil
   287  		case "%":
   288  			// Result will be int
   289  			return AsValue(f1.Integer() % f2.Integer()), nil
   290  		default:
   291  			panic("unimplemented")
   292  		}
   293  	} else {
   294  		return f1, nil
   295  	}
   296  }
   297  
   298  func (pw *power) Evaluate(ctx *ExecutionContext) (*Value, *Error) {
   299  	p1, err := pw.power1.Evaluate(ctx)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  	if pw.power2 != nil {
   304  		p2, err := pw.power2.Evaluate(ctx)
   305  		if err != nil {
   306  			return nil, err
   307  		}
   308  		return AsValue(math.Pow(p1.Float(), p2.Float())), nil
   309  	} else {
   310  		return p1, nil
   311  	}
   312  }
   313  
   314  func (p *Parser) parseFactor() (IEvaluator, *Error) {
   315  	if p.Match(TokenSymbol, "(") != nil {
   316  		expr, err := p.ParseExpression()
   317  		if err != nil {
   318  			return nil, err
   319  		}
   320  		if p.Match(TokenSymbol, ")") == nil {
   321  			return nil, p.Error("Closing bracket expected after expression", nil)
   322  		}
   323  		return expr, nil
   324  	}
   325  
   326  	return p.parseVariableOrLiteralWithFilter()
   327  }
   328  
   329  func (p *Parser) parsePower() (IEvaluator, *Error) {
   330  	pw := new(power)
   331  
   332  	power1, err := p.parseFactor()
   333  	if err != nil {
   334  		return nil, err
   335  	}
   336  	pw.power1 = power1
   337  
   338  	if p.Match(TokenSymbol, "^") != nil {
   339  		power2, err := p.parsePower()
   340  		if err != nil {
   341  			return nil, err
   342  		}
   343  		pw.power2 = power2
   344  	}
   345  
   346  	if pw.power2 == nil {
   347  		// Shortcut for faster evaluation
   348  		return pw.power1, nil
   349  	}
   350  
   351  	return pw, nil
   352  }
   353  
   354  func (p *Parser) parseTerm() (IEvaluator, *Error) {
   355  	return_term := new(term)
   356  
   357  	factor1, err := p.parsePower()
   358  	if err != nil {
   359  		return nil, err
   360  	}
   361  	return_term.factor1 = factor1
   362  
   363  	for p.PeekOne(TokenSymbol, "*", "/", "%") != nil {
   364  		if return_term.op_token != nil {
   365  			// Create new sub-term
   366  			return_term = &term{
   367  				factor1: return_term,
   368  			}
   369  		}
   370  
   371  		op := p.Current()
   372  		p.Consume()
   373  
   374  		factor2, err := p.parsePower()
   375  		if err != nil {
   376  			return nil, err
   377  		}
   378  
   379  		return_term.op_token = op
   380  		return_term.factor2 = factor2
   381  	}
   382  
   383  	if return_term.op_token == nil {
   384  		// Shortcut for faster evaluation
   385  		return return_term.factor1, nil
   386  	}
   387  
   388  	return return_term, nil
   389  }
   390  
   391  func (p *Parser) parseSimpleExpression() (IEvaluator, *Error) {
   392  	expr := new(simpleExpression)
   393  
   394  	if sign := p.MatchOne(TokenSymbol, "+", "-"); sign != nil {
   395  		if sign.Val == "-" {
   396  			expr.negative_sign = true
   397  		}
   398  	}
   399  
   400  	if p.Match(TokenSymbol, "!") != nil || p.Match(TokenKeyword, "not") != nil {
   401  		expr.negate = true
   402  	}
   403  
   404  	term1, err := p.parseTerm()
   405  	if err != nil {
   406  		return nil, err
   407  	}
   408  	expr.term1 = term1
   409  
   410  	for p.PeekOne(TokenSymbol, "+", "-") != nil {
   411  		if expr.op_token != nil {
   412  			// New sub expr
   413  			expr = &simpleExpression{
   414  				term1: expr,
   415  			}
   416  		}
   417  
   418  		op := p.Current()
   419  		p.Consume()
   420  
   421  		term2, err := p.parseTerm()
   422  		if err != nil {
   423  			return nil, err
   424  		}
   425  
   426  		expr.term2 = term2
   427  		expr.op_token = op
   428  	}
   429  
   430  	if expr.negate == false && expr.negative_sign == false && expr.term2 == nil {
   431  		// Shortcut for faster evaluation
   432  		return expr.term1, nil
   433  	}
   434  
   435  	return expr, nil
   436  }
   437  
   438  func (p *Parser) parseRelationalExpression() (IEvaluator, *Error) {
   439  	expr1, err := p.parseSimpleExpression()
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	expr := &relationalExpression{
   445  		expr1: expr1,
   446  	}
   447  
   448  	if t := p.MatchOne(TokenSymbol, "==", "<=", ">=", "!=", "<>", ">", "<"); t != nil {
   449  		expr2, err := p.parseRelationalExpression()
   450  		if err != nil {
   451  			return nil, err
   452  		}
   453  		expr.op_token = t
   454  		expr.expr2 = expr2
   455  	} else if t := p.MatchOne(TokenKeyword, "in"); t != nil {
   456  		expr2, err := p.parseSimpleExpression()
   457  		if err != nil {
   458  			return nil, err
   459  		}
   460  		expr.op_token = t
   461  		expr.expr2 = expr2
   462  	}
   463  
   464  	if expr.expr2 == nil {
   465  		// Shortcut for faster evaluation
   466  		return expr.expr1, nil
   467  	}
   468  
   469  	return expr, nil
   470  }
   471  
   472  func (p *Parser) ParseExpression() (IEvaluator, *Error) {
   473  	rexpr1, err := p.parseRelationalExpression()
   474  	if err != nil {
   475  		return nil, err
   476  	}
   477  
   478  	exp := &Expression{
   479  		expr1: rexpr1,
   480  	}
   481  
   482  	if p.PeekOne(TokenSymbol, "&&", "||") != nil || p.PeekOne(TokenKeyword, "and", "or") != nil {
   483  		op := p.Current()
   484  		p.Consume()
   485  		expr2, err := p.ParseExpression()
   486  		if err != nil {
   487  			return nil, err
   488  		}
   489  		exp.expr2 = expr2
   490  		exp.op_token = op
   491  	}
   492  
   493  	if exp.expr2 == nil {
   494  		// Shortcut for faster evaluation
   495  		return exp.expr1, nil
   496  	}
   497  
   498  	return exp, nil
   499  }