aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorErik Terpstra <erterpstra@gmail.com>2020-06-20 11:00:40 +0200
committerLouis Pilfold <louis@lpil.uk>2020-06-20 13:17:48 +0100
commitea3a318c0d6c133c8c05d9fa20a7adddc500ad75 (patch)
treea59508d7e1a89fea986692cc765ffe3cdef24d4f /src
parent8acab03caea114f5abbe40af59e1f6de207bce91 (diff)
downloadgleam_stdlib-ea3a318c0d6c133c8c05d9fa20a7adddc500ad75.tar.gz
gleam_stdlib-ea3a318c0d6c133c8c05d9fa20a7adddc500ad75.zip
Regex module
Diffstat (limited to 'src')
-rw-r--r--src/gleam/regex.gleam75
-rw-r--r--src/gleam_stdlib.erl29
2 files changed, 103 insertions, 1 deletions
diff --git a/src/gleam/regex.gleam b/src/gleam/regex.gleam
new file mode 100644
index 0000000..3740984
--- /dev/null
+++ b/src/gleam/regex.gleam
@@ -0,0 +1,75 @@
+//// This module contains regular expression matching functions for strings.
+//// The matching algorithms of the library are based on the PCRE library, but not
+//// all of the PCRE library is interfaced and some parts of the library go beyond
+//// what PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used.
+
+pub external type Regex
+
+/// When a regular expression fails to compile:
+///
+/// - error — a descriptive error message
+/// - index — the index of the cause in the regex string
+///
+pub type FromStringError {
+ FromStringError(error: String, index: Int)
+}
+
+/// Create a new Regex.
+///
+/// ## Examples
+///
+/// > let Ok(re) = from_string("[0-9]")
+/// > match(re, "abc123")
+/// True
+///
+/// > match(re, "abcxyz")
+/// False
+///
+/// > from_string("[0-9")
+/// Error(
+/// FromStringError(
+/// error: "missing terminating ] for character class",
+/// index: 4
+/// )
+/// )
+///
+pub external fn from_string(String) -> Result(Regex, FromStringError) =
+ "gleam_stdlib" "regex_from_string"
+
+pub type Options {
+ Options(case_insensitive: Bool, multi_line: Bool)
+}
+
+/// Create a Regex with some additional options.
+///
+/// ## Examples
+///
+/// > let options = Options(case_insensitive: False, multi_line: True)
+/// > let Ok(re) = from_string_with(options, "^[0-9]")
+/// > match(re, "abc\n123")
+/// True
+///
+/// > let options = Options(case_insensitive: True, multi_line: False)
+/// > let Ok(re) = from_string_with(options, "[A-Z]")
+/// > match(re, "abc123")
+/// True
+///
+pub external fn from_string_with(
+ Options,
+ String,
+) -> Result(Regex, FromStringError) =
+ "gleam_stdlib" "regex_from_string_with"
+
+/// Returns a boolean indicating whether there was a match or not.
+///
+/// ## Examples
+///
+/// > let Ok(re) = from_string("^f.o.?")
+/// > match(re, "foo")
+/// True
+///
+/// > match(re, "boo")
+/// False
+///
+pub external fn match(Regex, String) -> Bool =
+ "gleam_stdlib" "regex_match"
diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl
index 4b9c6a1..f0adbd0 100644
--- a/src/gleam_stdlib.erl
+++ b/src/gleam_stdlib.erl
@@ -10,7 +10,8 @@
string_pop_grapheme/1, string_starts_with/2, string_ends_with/2,
string_pad/4, decode_tuple2/1, decode_map/1, bit_string_int_to_u32/1,
bit_string_int_from_u32/1, bit_string_append/2, bit_string_part_/3,
- decode_bit_string/1]).
+ decode_bit_string/1, regex_from_string/1, regex_from_string_with/2,
+ regex_match/2]).
should_equal(Actual, Expected) -> ?assertEqual(Expected, Actual).
should_not_equal(Actual, Expected) -> ?assertNotEqual(Expected, Actual).
@@ -162,3 +163,29 @@ bit_string_int_from_u32(<<I:32>>) ->
{ok, I};
bit_string_int_from_u32(_) ->
{error, nil}.
+
+regex_from_string_with_opts(Options, String) ->
+ case re:compile(String, Options) of
+ {ok, MP} -> {ok, MP};
+ {error, {Str, Pos}} ->
+ {error, {from_string_error, unicode:characters_to_binary(Str), Pos}}
+ end.
+
+regex_from_string(String) ->
+ regex_from_string_with_opts([unicode], String).
+
+regex_from_string_with(Options, String) ->
+ OptList = case Options of
+ {options, true, _} -> [unicode, caseless];
+ _ -> [unicode]
+ end,
+ case Options of
+ {options, _, true} -> regex_from_string_with_opts([multiline | OptList], String);
+ _ -> regex_from_string_with_opts(OptList, String)
+ end.
+
+regex_match(Regex, String) ->
+ case re:run(String, Regex) of
+ {match, _} -> true;
+ _ -> false
+ end.