# `Cldr.Number.Format.Compiler`
[🔗](https://github.com/elixir-cldr/cldr_numbers/blob/v2.38.1/lib/cldr/number/format/compiler.ex#L1)

Compiles number patterns with a lexer/parser into patterns for fast runtime interpretation.

Number patterns affect how numbers are interpreted in a localized context.
Here are some examples, based on the French locale. The "." shows where the
decimal point should go. The "," shows where the thousands separator should go.
A "0" indicates zero-padding: if the number is too short, a zero (in the
locale's numeric set) will go there. A "#" indicates no padding: if the number
is too short, nothing goes there. A "¤" shows where the currency sign will go.
The following illustrates the effects of different patterns for the French
locale, with the number "1234.567". Notice how the pattern characters ',' and
'.' are replaced by the characters appropriate for the locale.

### Number Pattern Examples

Pattern	   | Currency	 | Text
---------- | --------- | ----------
#,##0.##	 | n/a	     | 1 234,57
#,##0.###	 | n/a	     | 1 234,567
###0.##### | n/a	     | 1234,567
###0.0000# | n/a	     | 1234,5670
00000.0000 | n/a	     | 01234,5670
#,##0.00 ¤ | EUR	     | 1 234,57 €

The number of # placeholder characters before the decimal do not matter,
since no limit is placed on the maximum number of digits. There should,
however, be at least one zero someplace in the pattern. In currency formats,
the number of digits after the decimal also do not matter, since the
information in the supplemental data (see Supplemental Currency Data) is used
to override the number of decimal places — and the rounding — according to
the currency that is being formatted. That can be seen in the above chart,
with the difference between Yen and Euro formatting.

## Special Pattern Characters

Many characters in a pattern are taken literally; they are matched during
parsing and output unchanged during formatting. Special characters, on the
other hand, stand for other characters, strings, or classes of characters.
For example, the '#' character is replaced by a localized digit for the
chosen numberSystem. Often the replacement character is the same as the
pattern character; in the U.S. locale, the ',' grouping character is replaced
by ','. However, the replacement is still happening, and if the symbols are
modified, the grouping character changes. Some special characters affect the
behavior of the formatter by their presence; for example, if the percent
character is seen, then the value is multiplied by 100 before being displayed.

To insert a special character in a pattern as a literal, that is, without any
special meaning, the character must be quoted. There are some exceptions to
this which are noted below.

### Number Pattern Character Definitions

Symbol | Meaning
------ | -------
0	     | Digit
1..9   | '1' through '9' indicate rounding to the nearest `n`
@	     | Significant digit
#	     | Digit, omitting leading/trailing zeros
.	     | Decimal separator or monetary decimal separator
-	     | Minus sign
,	     | Grouping separator
+	     | Prefix positive exponents with localized plus sign
%	     | Multiply by 100 and show as percentage
‰      | Multiply by 1000 and show as per mille (aka “basis points”)
;	     | Separates positive and negative subpatterns
¤      | Any sequence is replaced by the localized currency symbol
*	     | Pad escape, precedes pad character
'	     | Used to quote special characters in a prefix or suffix

A pattern contains a positive subpattern and may contain a negative
subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix,
a numeric part, and a suffix. If there is no explicit negative subpattern,
the implicit negative subpattern is the ASCII minus sign (-) prefixed to the
positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00".
(The data in CLDR is normalized to remove an explicit subpattern where it
would be identical to the explicit form.) If there is an explicit negative
subpattern, it serves only to specify the negative prefix and suffix; the
number of digits, minimal digits, and other characteristics are ignored in
the negative subpattern. That means that "#,##0.0#;(#)" has precisely the
same result as "#,##0.0#;(#,##0.0#)". However in the CLDR data, the format is
normalized so that the other characteristics are preserved, just for
readability.

Note: The thousands separator and decimal separator in patterns are always
ASCII ',' and '.'. They are substituted by the code with the correct local
values according to other fields in CLDR. The same is true of the - (ASCII
minus sign) and other special characters listed above.

Extracted from [Unicode number formats in TR35](http://unicode.org/reports/tr35/tr35-numbers.html#Number_Formats)

# `compile`

Parse a number format definition and analyze it.

After parsing, reduce the format to a set of metrics
that can then be used to format a number.

# `exponent_sign`

# `format_to_metadata`

Extract the metadata from the format.

The metadata is used to generate the formatted output.  A numeric format
is optional and in such cases no analysis is required.

# `format_to_metadata!`

Extract the metadata from the format or raise
an exception..

The metadata is used to generate the formatted output.  A numeric format
is optional and in such cases no analysis is required.

# `formatting_pipeline`

Returns an Elixir AST of a formatting pipeline that
when executed produces the formatted output for a given
format string.

Not all formats require all parts of the full formatting
pipeline so by compiling only those parts of the pipeline
that are required we produce an optimal code path.

# `number_match_regex`

A regular expression that can be used to split either a number format
or a number itself.

Since it accepts characters that are not digits (like '#', '@' and
',') it cannot be used to validate a number.  Its only use is to split
a number or a format into parts for later processing.

# `padding_char`

# `parse`

Parse a number format definition

Using a yexx lexer, parse a number format definition into list of
elements we can then interpret to format a number.

## Example

    iex> Cldr.Number.Format.Compiler.parse "¤ #,##0.00;¤-#,##0.00"
    {:ok,
     [positive: [currency: 1, literal: " ", format: "#,##0.00"],
      negative: [currency: 1, minus: ~c"-", format: :same_as_positive]]}

# `placeholder`

```elixir
@spec placeholder(
  :decimal
  | :group
  | :exponent
  | :exponent_sign
  | :plus
  | :minus
  | :currency
) ::
  String.t()
```

Returns a number placeholder symbol.

* `symbol` is one of `:decimal`, `group`, `:exponent`,
`:plus`, `:minus`, `:currency`

These symbols are used in decimal number format
and are replaced with locale-specific characters
during number formatting.

## Example

    iex> Cldr.Number.Format.Compiler.placeholder(:plus)
    "+"

# `tokenize`

Scan a number format definition

Using a leex lexer, tokenize a rule definition

---

*Consult [api-reference.md](api-reference.md) for complete listing*
