RegexTransformer constructor

RegexTransformer({
  1. required RegExp regex,
  2. required String output,
  3. Map<String, dynamic>? variables,
  4. bool math = false,
  5. bool strict = false,
})

A RegExp paired with an output template that matches input text with the RegExp and returns a new string based on the template with the capture groups matched by the RegExp filled in.

regex defines the RegExp utilized by the transform method. Only the first match found in the text provided to transform will be included in the text it outputs.

Named capture groups defined within regex may only contain alphanumeric characters (a-z, A-Z, 0-9) and underscores (_).

output defines the template the text output by the transform method will follow. Capture groups matched by the regex may be defined within output by their respective names or indexes preceded by a $, as such if supplying a hardcoded output, it's recommended to supply output as a raw string (r'...'), otherwise every $ will have to be escaped. Note: To output a $ without having it interpreted as an annotation defining a capture group, it must be escaped (\$). If included in a string that isn't raw, the $ and the \ preceding it must both be escaped (\\\$).

/// This transformer defines 3 indexed capture groups and
/// returns them as defined by the output template.
final transformer = RegexTransformer(
  regex: RegExp(r'(.*) .* (.*) .* (.*)'),
  output: r'$1 + $2 = $3',
);

// one + two = fish
print(transformer.transform('one plus two equals fish'));

Expressions can be built within the output template and evaluated by the transformation methods. Expressions are defined by the $ annotation then wrapping the expression with parentheses: $(...).

Note: Expressions are parsed and evaluated utilizing the expressions package.

/// This transformer evaluates an expression and outputs the result.
final transformer = RegexTransformer(
  regex: RegExp(r'(?<one>[0-9]).*(?<two>[0-9])'),
  output: r'$one + $two = $($one + $two)',
);

// 2 + 3 = 5
print(transformer.transform('2 + 3 = fish'));

variables can be provided to map variables and functions to the expression evaluator's context.

/// Expressions defined in this transformer's output template can
/// utilize the `ceil` and `combine` functions provided to it.
final transformer = RegexTransformer(
  regex: RegExp(r'([0-9]) \+ ([0-9]) = ([a-z]*)'),
  variables: {
    'ceil': (double input) => input.ceil(),
    'combine': (String input) => input.codeUnits.reduce((a, b) => a + b),
  },
  output: r'$1 + $2 = $(ceil(combine($3) / 100))',
);

// 2 + 3 = 5
print(transformer.transform('2 + 3 = fish'));

math, if true, will map every constant and function from the dart:math library to the expression evaluator's context, as well as the abs, ceil, floor, and round methodds from num, allowing them to be parsed and evaluated within any expressions included in the output template.

/// Expressions defined in this transformer's output template can
/// utilize the `dart:math` library's methods and functions, as well
/// as the `abs`, `ceil`, `floor`, and `round` methods from [num].
final transformer = RegexTransformer(
  regex: RegExp(r'([0-9]) \+ ([0-9]) = ([a-z]*)'),
  output: r'$3 = $(round((sin(($2 * pi) * ($2 / $1)) +'
      r'cos(($1 * pi) * ($1 / $2))) * 10))',
  math: true,
);

// fish = 5
print(transformer.transform('2 + 3 = fish'));

Note: If math is true, variables may not contain any keys equivalent to the names of any of the dart:math library's constants and functions.

If strict is set to true, an ArgumentError will be thrown if any capture group annotated in the output template isn't matched in the text provided to the transformation methods, or a FormatException if an expression can't be parsed or evaluated. However, if strict is false any capture groups that aren't matched will be treated as plain text. If any unmatched capture groups are part of an expression, the expression will also be output as plain text with any of the capture groups that were matched replaced with their respective values.

Implementation

RegexTransformer({
  required this.regex,
  required this.output,
  this.variables,
  this.math = false,
  this.strict = false,
})  : assert(
          !math ||
              variables == null ||
              variables.keys.every((expression) =>
                  !_Expression._mathExpressions.keys.contains(expression)),
          '[variables] may not contain any keys reserved by [math].'),
      _output = _OutputTemplate.from(output,
          strict: strict, variables: variables, math: math);