...

Source file src/github.com/noirbizarre/gonja/parser/math.go

Documentation: github.com/noirbizarre/gonja/parser

     1  package parser
     2  
     3  import (
     4  	// "fmt"
     5  
     6  	"fmt"
     7  
     8  	"github.com/noirbizarre/gonja/nodes"
     9  	"github.com/noirbizarre/gonja/tokens"
    10  	log "github.com/sirupsen/logrus"
    11  )
    12  
    13  // type unary struct {
    14  // 	negative bool
    15  // 	term     nodes.Expression
    16  // 	operator *Token
    17  // }
    18  
    19  // func (expr *unary) String() string {
    20  // 	t := expr.GetPositionToken()
    21  
    22  // 	return fmt.Sprintf("<Unary sign=%s term=%s Line=%d Col=%d>",
    23  // 		expr.operator.Val, expr.term, t.Line, t.Col)
    24  // }
    25  
    26  // func (expr *unary) FilterApplied(name string) bool {
    27  // 	return expr.term.FilterApplied(name)
    28  // }
    29  
    30  // func (expr *unary) GetPositionToken() *Token {
    31  // 	return expr.operator
    32  // }
    33  
    34  // func (expr *unary) Execute(ctx *ExecutionContext, writer TemplateWriter) error {
    35  // 	value, err := expr.Evaluate(ctx)
    36  // 	if err != nil {
    37  // 		return err
    38  // 	}
    39  // 	writer.WriteString(value.String())
    40  // 	return nil
    41  // }
    42  
    43  // func (expr *unary) Evaluate(ctx *ExecutionContext) (*Value, error) {
    44  // 	result, err := expr.term.Evaluate(ctx)
    45  // 	if err != nil {
    46  // 		return nil, err
    47  // 	}
    48  // 	if expr.negative {
    49  // 		if result.IsNumber() {
    50  // 			switch {
    51  // 			case result.IsFloat():
    52  // 				result = AsValue(-1 * result.Float())
    53  // 			case result.IsInteger():
    54  // 				result = AsValue(-1 * result.Integer())
    55  // 			default:
    56  // 				return nil, ctx.Error("Operation between a number and a non-(float/integer) is not possible", nil)
    57  // 			}
    58  // 		} else {
    59  // 			return nil, ctx.Error("Negative sign on a non-number expression", expr.GetPositionToken())
    60  // 		}
    61  // 	}
    62  
    63  // 	return result, nil
    64  // }
    65  
    66  func (p *Parser) ParseMath() (nodes.Expression, error) {
    67  	log.WithFields(log.Fields{
    68  		"current": p.Current(),
    69  	}).Trace("ParseMath")
    70  
    71  	expr, err := p.parseConcat()
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	for p.Peek(tokens.Add, tokens.Sub) != nil {
    77  		op := BinOp(p.Pop())
    78  		right, err := p.parseConcat()
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		expr = &nodes.BinaryExpression{
    83  			Left:     expr,
    84  			Right:    right,
    85  			Operator: op,
    86  		}
    87  	}
    88  
    89  	log.WithFields(log.Fields{
    90  		"expr": expr,
    91  	}).Trace("ParseMath return")
    92  	return expr, nil
    93  }
    94  
    95  func (p *Parser) parseConcat() (nodes.Expression, error) {
    96  	log.WithFields(log.Fields{
    97  		"current": p.Current(),
    98  	}).Trace("parseConcat")
    99  
   100  	expr, err := p.ParseMathPrioritary()
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	for p.Peek(tokens.Tilde) != nil {
   106  		op := BinOp(p.Pop())
   107  		right, err := p.ParseMathPrioritary()
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		expr = &nodes.BinaryExpression{
   112  			Left:     expr,
   113  			Right:    right,
   114  			Operator: op,
   115  		}
   116  	}
   117  
   118  	log.WithFields(log.Fields{
   119  		"expr": expr,
   120  	}).Trace("parseConcat return")
   121  	return expr, nil
   122  }
   123  
   124  func (p *Parser) ParseMathPrioritary() (nodes.Expression, error) {
   125  	log.WithFields(log.Fields{
   126  		"current": p.Current(),
   127  	}).Trace("ParseMathPrioritary")
   128  
   129  	expr, err := p.parseUnary()
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	for p.Peek(tokens.Mul, tokens.Div, tokens.Floordiv, tokens.Mod) != nil {
   135  		op := BinOp(p.Pop())
   136  		right, err := p.parseUnary()
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		expr = &nodes.BinaryExpression{
   141  			Left:     expr,
   142  			Right:    right,
   143  			Operator: op,
   144  		}
   145  	}
   146  
   147  	log.WithFields(log.Fields{
   148  		"expr": expr,
   149  	}).Trace("ParseMathPrioritary return")
   150  	return expr, nil
   151  }
   152  
   153  func (p *Parser) parseUnary() (nodes.Expression, error) {
   154  	log.WithFields(log.Fields{
   155  		"current": p.Current(),
   156  	}).Trace("parseUnary")
   157  
   158  	sign := p.Match(tokens.Add, tokens.Sub)
   159  
   160  	expr, err := p.ParsePower()
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	if sign != nil {
   166  		expr = &nodes.UnaryExpression{
   167  			Operator: sign,
   168  			Negative: sign.Val == "-",
   169  			Term:     expr,
   170  		}
   171  	}
   172  
   173  	log.WithFields(log.Fields{
   174  		"expr": expr,
   175  	}).Trace("parseUnary return")
   176  	return expr, nil
   177  }
   178  
   179  func (p *Parser) ParsePower() (nodes.Expression, error) {
   180  	log.WithFields(log.Fields{
   181  		"current": p.Current(),
   182  	}).Trace("ParsePower")
   183  
   184  	expr, err := p.ParseVariableOrLiteral()
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	for p.Peek(tokens.Pow) != nil {
   190  		op := BinOp(p.Pop())
   191  		right, err := p.ParseVariableOrLiteral()
   192  		if err != nil {
   193  			return nil, err
   194  		}
   195  		expr = &nodes.BinaryExpression{
   196  			Left:     expr,
   197  			Right:    right,
   198  			Operator: op,
   199  		}
   200  	}
   201  
   202  	log.WithFields(log.Fields{
   203  		"type": fmt.Sprintf("%T", expr),
   204  		"expr": expr,
   205  	}).Trace("ParsePower return")
   206  	return expr, nil
   207  }
   208  

View as plain text