Color.CSS.Calc (Color v0.4.0)

Copy Markdown

A tiny calc() expression evaluator for CSS color components.

Supports:

  • Numeric literals (255, 0.5, -1.2).

  • Percentages (50%) — interpreted as the raw percent value (50.0), not as a fraction. Channel parsers in Color.CSS decide whether to scale.

  • The four arithmetic operators + - * / with the conventional precedence and associativity.

  • Parenthesised sub-expressions.

  • Identifier references (r, g, b, h, s, l, alpha, …) that resolve against a bindings map. This is what makes relative color syntax (oklch(from teal calc(l + 0.1) c h)) work.

  • The none keyword — evaluated as 0.0.

Whitespace is ignored.

Example

iex> {:ok, ast} = Color.CSS.Calc.parse("255 / 2")
iex> {:ok, value} = Color.CSS.Calc.evaluate(ast, %{})
iex> value
127.5

iex> {:ok, ast} = Color.CSS.Calc.parse("l + 0.1")
iex> {:ok, value} = Color.CSS.Calc.evaluate(ast, %{"l" => 0.5})
iex> Float.round(value, 4)
0.6

iex> {:ok, ast} = Color.CSS.Calc.parse("(r + g + b) / 3")
iex> {:ok, value} = Color.CSS.Calc.evaluate(ast, %{"r" => 200, "g" => 100, "b" => 50})
iex> Float.round(value, 4)
116.6667

Summary

Functions

Evaluates a parsed calc() AST against a binding map.

Parses a calc() body into an AST.

Functions

evaluate(ast, bindings)

Evaluates a parsed calc() AST against a binding map.

Arguments

  • ast is a value returned by parse/1.

  • bindings is a map from identifier strings to numeric values.

Returns

  • {:ok, float} on success.

  • {:error, reason} on division by zero or unbound identifier.

parse(string)

Parses a calc() body into an AST.

Arguments

  • string is the body of a calc(...) expression — everything between the outermost parens.

Returns

  • {:ok, ast} on success.

  • {:error, reason} on a parse error.