func (parser *Parser) ParseNumber() ast.Expr { var pos = parser.Pos debug("ParseNumber at %d", parser.Pos) // the number token var tok = parser.next() debug("ParseNumber => next: %s", tok) var negative = false if tok.Type == ast.T_MINUS { tok = parser.next() negative = true } else if tok.Type == ast.T_PLUS { tok = parser.next() negative = false } var val float64 var tok2 = parser.peek() if tok.Type == ast.T_INTEGER { i, err := strconv.ParseInt(tok.Str, 10, 64) if err != nil { panic(err) } if negative { i = -i } val = float64(i) } else if tok.Type == ast.T_FLOAT { f, err := strconv.ParseFloat(tok.Str, 64) if err != nil { panic(err) } if negative { f = -f } val = f } else { // unknown token parser.restore(pos) return nil } if tok2.IsUnit() { // consume the unit token parser.next() return ast.NewNumber(val, ast.NewUnitWithToken(tok2), tok) } return ast.NewNumber(val, nil, tok) }
/* 10px / 3, 10 / 3, 10px / 10px is allowed here */ func NumberDivNumber(a *ast.Number, b *ast.Number) *ast.Number { // for 10/2 and 10px/2px if (a.Unit == nil && b.Unit == nil) || (a.Unit != nil && b.Unit != nil && a.Unit.Type == b.Unit.Type) { return ast.NewNumber(a.Value/b.Value, nil, nil) } if a.Unit != nil && b.Unit == nil { return ast.NewNumber(a.Value/b.Value, a.Unit, nil) } return nil }
func TestStack(t *testing.T) { var stack = &Stack{} stack.Push(ast.NewNumber(10, nil, nil)) stack.Push(ast.NewNumber(12, nil, nil)) val1 := stack.Pop() num1, ok := val1.(*ast.Number) assert.True(t, ok) assert.Equal(t, 12.0, num1.Value) val2 := stack.Pop() num2, ok := val2.(*ast.Number) assert.True(t, ok) assert.Equal(t, 10.0, num2.Value) }
func NumberAddNumber(a *ast.Number, b *ast.Number) *ast.Number { if (a.Unit == nil && b.Unit == nil) || (a.Unit != nil && b.Unit != nil && a.Unit.Type == b.Unit.Type) { return ast.NewNumber(a.Value+b.Value, a.Unit, nil) } fmt.Printf("Incompatible unit %s != %s. %v + %v \n", a.Unit, b.Unit, a, b) return nil }
func NumberSubNumber(a *ast.Number, b *ast.Number) *ast.Number { if a.Unit != nil && b.Unit != nil && a.Unit.Type != b.Unit.Type { fmt.Printf("Incompatible unit %s != %s. %v - %v \n", a.Unit, b.Unit, a, b) return nil } var result = a.Value - b.Value return ast.NewNumber(result, a.Unit, nil) }
/* 3 * 10px, 10px * 3, 10px * 10px is allowed here */ func NumberMulNumber(a *ast.Number, b *ast.Number) *ast.Number { if a.Unit == nil && b.Unit == nil { return ast.NewNumber(a.Value*b.Value, nil, nil) } if a.Unit == nil || b.Unit == nil || a.Unit.Type == b.Unit.Type { var result = a.Value * b.Value var unit *ast.Unit = nil if a.Unit != nil { unit = a.Unit } if b.Unit != nil { unit = b.Unit } return ast.NewNumber(result, unit, nil) } return nil }