Unicode.Set.Operation (Unicode Set v1.9.0)

Copy Markdown View Source

Functions to operate on Unicode sets:

  • Intersection
  • Difference
  • Union
  • Inversion

Summary

Functions

Combines the terms of a union-only expression tree into a flat list of {:in, ranges} and {:not_in, ranges} terms.

Merges overlapping and adjacent code point ranges.

Returns the code point complement of a set or a range list.

Returns the difference of two lists of code point ranges.

Expands a reduced set, or a reduced expression tree, into a single positive list of code point ranges.

Expands any string ranges in a range list into their individual string members.

Returns whether an expression tree contains an intersection or a difference.

Returns the intersection of two lists of code point ranges.

Evaluates the set operations of a parsed set, leaving a list of code point ranges.

Returns the symmetric difference of two lists of code point ranges.

Walks a reduced set, invoking a function on each code point range, and returns the results.

Returns the union of two lists of code point ranges.

Functions

combine(other)

Combines the terms of a union-only expression tree into a flat list of {:in, ranges} and {:not_in, ranges} terms.

This is the fast path used by reduce/1 when an expression contains no intersection or difference; otherwise the tree must be expanded with expand/1.

Arguments

  • ast is a parsed expression term.

Returns

  • A list of {:in, ranges} and {:not_in, ranges} terms, or a single such term.

compact_ranges(terms)

Merges overlapping and adjacent code point ranges.

Arguments

  • ranges is a sorted list of {first, last} code point ranges and string members, or an {:in, ranges} or {:not_in, ranges} term, or a list of such terms.

Returns

  • The same shape with overlapping and adjacent code point ranges merged. String members are deduplicated but otherwise kept as written.

Examples

iex> Unicode.Set.Operation.compact_ranges([{1, 2}, {3, 4}, {4, 9}])
[{1, 9}]

iex> Unicode.Set.Operation.compact_ranges({:in, [{97, 98}, {99, 99}]})
{:in, [{97, 99}]}

complement(set)

Returns the code point complement of a set or a range list.

Arguments

  • set is a Unicode.Set.t/0 in any state, or a list of {first, last} code point ranges.

Returns

  • For a Unicode.Set.t/0, the set with {:in, ranges} and {:not_in, ranges} exchanged.

  • For a range list, the list of code points from U+0000 to U+10FFFF that are not in it.

Examples

iex> Unicode.Set.Operation.complement([{0, 96}, {98, 1114111}])
[{97, 97}]

difference(a, b)

Returns the difference of two lists of code point ranges.

Arguments

  • a and b are sorted lists of {first, last} code point ranges with no overlapping ranges, as compact_ranges/1 returns them.

Returns

  • A sorted list of the code point ranges in a that are not in b.

Examples

iex> Unicode.Set.Operation.difference([{1, 10}], [{3, 4}, {8, 20}])
[{1, 2}, {5, 7}]

expand(unicode_set)

Expands a reduced set, or a reduced expression tree, into a single positive list of code point ranges.

Arguments

  • unicode_set is a reduced Unicode.Set.t/0, or a reduced expression term such as {:not_in, ranges} or {:union, [this, that]}.

Returns

  • For a Unicode.Set.t/0, the set with its :parsed field replaced by the expanded range list and its :state set to :expanded.

  • For a term, the expanded range list.

Examples

iex> Unicode.Set.parse_and_reduce!("[^a]") |> Unicode.Set.Operation.expand() |> Map.get(:parsed)
[{0, 96}, {98, 1114111}]

expand_string_range(arg1)

expand_string_ranges(ranges)

Expands any string ranges in a range list into their individual string members.

Arguments

  • ranges is a list of code point ranges and string ranges, where a string range is a {from, to} pair of charlists of the same length.

Returns

  • The range list with each string range replaced by one {string, string} member per string in the range.

Examples

iex> Unicode.Set.Operation.expand_string_ranges([{97, 97}, {~c"ab", ~c"ad"}])
[{97, 97}, {~c"ab", ~c"ab"}, {~c"ac", ~c"ac"}, {~c"ad", ~c"ad"}]

has_difference_or_intersection?(arg1)

Returns whether an expression tree contains an intersection or a difference.

When it does, every range, including a complement, must be expanded before the operation can be evaluated. When it does not, a complement can be passed through as {:not_in, ranges}.

Arguments

  • ast is a parsed expression term.

Returns

  • true or false.

Examples

iex> Unicode.Set.Operation.has_difference_or_intersection?(Unicode.Set.parse!("[[a-z]&[m-z]]").parsed)
true

iex> Unicode.Set.Operation.has_difference_or_intersection?(Unicode.Set.parse!("[[a-z][m-z]]").parsed)
false

intersect(a, b)

Returns the intersection of two lists of code point ranges.

Arguments

  • a and b are sorted lists of {first, last} code point ranges with no overlapping ranges, as compact_ranges/1 returns them.

Returns

  • A sorted list of the code point ranges common to both.

Examples

iex> Unicode.Set.Operation.intersect([{1, 5}, {10, 20}], [{3, 12}])
[{3, 5}, {10, 12}]

reduce(unicode_set)

Evaluates the set operations of a parsed set, leaving a list of code point ranges.

A complement is preserved as {:not_in, ranges} for as long as possible, since guards, regexes and nimble_parsec can all consume an exclusion directly. Only an intersection or difference forces the ranges to be expanded into positive form.

Arguments

Returns

  • The Unicode.Set.t/0 with its :parsed field replaced by {:in, ranges}, {:not_in, ranges} or a list of such terms, and its :state set to :reduced.

Examples

iex> Unicode.Set.parse!("[[a-z]&[m-z]]") |> Unicode.Set.Operation.reduce() |> Map.get(:parsed)
{:in, [{109, 122}]}

iex> Unicode.Set.parse!("[^a-z]") |> Unicode.Set.Operation.reduce() |> Map.get(:parsed)
{:not_in, [{97, 122}]}

symmetric_difference(this, that)

Returns the symmetric difference of two lists of code point ranges.

Arguments

  • this and that are lists of {first, last} code point ranges.

Returns

  • A sorted list of the code point ranges in either list but not in both.

Examples

iex> Unicode.Set.Operation.symmetric_difference([{1, 5}], [{3, 8}])
[{1, 2}, {6, 8}]

traverse(ranges, fun)

Walks a reduced set, invoking a function on each code point range, and returns the results.

This is how the transforms to guards, patterns, utf8_char/1 lists and regex strings are built.

Arguments

  • set is a reduced Unicode.Set.t/0, or its :parsed field.

  • var is an optional term passed through to fun, used to build guard clauses around a variable.

  • fun is a function of a range, the accumulated result and var.

Returns

  • The result of applying fun across the ranges.

traverse(range, var, fun)

union(a_list, b_list)

Returns the union of two lists of code point ranges.

Arguments

  • a_list and b_list are lists of {first, last} code point ranges.

Returns

  • A sorted, compacted list of the code point ranges in either list.

Examples

iex> Unicode.Set.Operation.union([{1, 3}, {10, 12}], [{4, 6}])
[{1, 6}, {10, 12}]