This document provides usage examples and pattern matching examples with expected Prolog toplevel outputs for the pure_regex library.
To load the regular expression engine, run:
?- use_module(library(pure_regex)).
true.Match a string directly against a regular expression pattern using phrase/2. When a pattern is written as a literal character list ("...") or atom ('...'), pure_regex compiles it ahead of time via goal_expansion/2 and inlines the compiled automaton term directly into the clause. Patterns compiled from literals bypass the dynamic compilation cache entirely, saving heap memory and avoiding cache lookup overhead. When a pattern is supplied dynamically at runtime via a variable, it is compiled on first use and cached in the dynamic pattern database.
?- phrase(re_match("a.*b", Match), "acb").
Match = "acb"
; false.Compile a regular expression pattern string into a reusable compiled structure.
?- re_compile("a.*b", Compiled).
Compiled = compiled_tree(sym(char(a),star(sym(dot,end,stp),sym(char(b),end,stp)),stp),0)
; false.Execute a pre-compiled pattern inside phrase/2 for maximum performance. Passing a pre-compiled pattern to re_match//1-2 avoids both pattern parsing overhead and cache lookup overhead on subsequent matches.
?- re_compile("a.*b", Compiled), phrase(re_match(Compiled, Match), "acb").
Compiled = compiled_tree(sym(char(a),star(sym(dot,end,stp),sym(char(b),end,stp)),stp),0)
Match = "acb"
; false.Inspect the dynamic compilation cache using re_cache_info/2 to check the number of cached patterns and their pattern keys. Statically compiled literal patterns bypass this cache (Count = 0). When patterns are passed dynamically via variables at runtime, they enter the dynamic cache:
?- re_clear_cache, P1 = "a.*b", phrase(re_match(P1), "acb"), P2 = "[0-9]+", phrase(re_match(P2), "123"), re_cache_info(Count, Keys).
Count = 4
Keys = ["a.*b", "a.*b", "[0-9]+", "[0-9]+"]
; false.Clear all compiled pattern goals from the dynamic compilation database using re_clear_cache/0. Note that re_clear_cache/0 is intended for the rare circumstance that an excessive number of distinct patterns have been compiled, resulting in excessive memory use by the Prolog system. In normal operation, compiled pattern caching provides substantial performance benefits without requiring manual invalidation.
?- re_clear_cache, re_cache_info(Count, Keys).
Count = 0
Keys = ""
; false.pure_regex provides compile-time macro expansion to eliminate pattern compilation latency at runtime:
- Approach A (Default, Goal Expansion): When a literal character list (
"...") or atom ('...') is passed tore_match/2-3,re_match_groups/4-5, orre_match_named/4-5,goal_expansion/2compiles the pattern during file loading. The resulting automaton is embedded directly as a constant term in the compiled clause. Patterns compiled from literals bypass the dynamic pattern cache entirely. - Approach B (DCG Rule Generation via
re_rule//0): Define dedicated, named DCG grammar rules directly from regular expressions at compile time:re_rule(ident//0, "^[a-zA-Z_][a-zA-Z0-9_]*$"). re_rule(ident_match(Match)//0, "^[a-zA-Z_][a-zA-Z0-9_]*$"). re_rule(ident_groups(Match, Groups)//0, "^([a-z]+)-([0-9]+)$").
- Default Engine Selection: Set the default regex engine globally via
user:regexp_engine(Engine)(rt[default] ordcg). - Static Compilation Toggle: Enable or disable compile-time macro expansion via
user:regexp_static_compilation(true | false). Whenfalse, literal patterns pass through to runtime dynamic matching. - Independent Static / Dynamic Overrides: Override matching engines separately:
user:regexp_static_engine(Engine): overrides the engine used for compile-time static compilation (rtordcg).user:regexp_dynamic_engine(Engine): overrides the engine used for runtime dynamic pattern matching (rtordcg).
- Expansion Strategy Mode: Select the expansion strategy via
user:regexp_expansion(Mode)(term[default, Approach A] orrules[Approach B]).
Basic matching of a literal character sequence.
?- phrase(re_match("abc", Match), "abc").
Match = "abc"
; false.Matching either sub-expression in alternation.
?- phrase(re_match("a|bc", Match), "bc").
Match = "bc"
; false.Explicit precedence using grouping parentheses.
?- phrase(re_match("(a|b)c", Match), "ac").
Match = "ac"
; false.Match zero or more times greedily.
?- phrase(re_match("a*", Match), "aaa").
Match = "aaa"
; false.Match one or more times greedily.
?- phrase(re_match("a+", Match), "aa").
Match = "aa"
; false.Match zero or one time greedily (optional matches).
?- phrase(re_match("a?", Match), "a").
Match = "a"
; false.Match zero or one time greedily (empty match).
?- phrase(re_match("a?", Match), "").
Match = ""
; false.Match exactly N times.
?- phrase(re_match("a{3}", Match), "aaa").
Match = "aaa"
; false.Match between N and M times greedily.
?- phrase(re_match("a{2,4}", Match), "aaaa").
Match = "aaaa"
; false.Extract substrings captured by groups. Captured groups are returned in group-number order (left-to-right based on the position of their opening parentheses). See: https://docs.oracle.com/javase/tutorial/essential/regex/groups.html
?- phrase(re_match_groups("(abc)", Match, Groups), "abc").
Match = "abc"
Groups = ["abc"]
; false.Extract substrings captured by nested groups. The groups are returned in group-number order (left-to-right based on the position of their opening parentheses), so the outer group comes first. See: https://docs.oracle.com/javase/tutorial/essential/regex/groups.html
?- phrase(re_match_groups("(a(b)c)", Match, Groups), "abc").
Match = "abc"
Groups = ["abc", "b"]
; false.Edge case: greedy star matching empty string.
?- phrase(re_match("a*", Match), "").
Match = ""
; false.Edge case: nested star operator.
?- phrase(re_match("(a*)*", Match), "a").
Match = "a"
; false.Match any single character listed in brackets.
?- phrase(re_match("[abc]", Match), "b").
Match = "b"
; false.Match any single character not listed in brackets.
?- phrase(re_match("[^abc]", Match), "d").
Match = "d"
; false.Match any single character except newline.
?- phrase(re_match("a.c", Match), "abc").
Match = "abc"
; false.Match any digit character via \d.
?- phrase(re_match("\\d", Match), "5").
Match = "5"
; false.Match any alphanumeric character plus underscore via \w.
?- phrase(re_match("\\w", Match), "x").
Match = "x"
; false.Match beginning of the input string via ^.
?- phrase(re_match("^a", Match), "a").
Match = "a"
; false.Match end of the input string via $.
?- phrase(re_match("a$", Match), "a").
Match = "a"
; false.Match minimal number of repetitions via *?.
?- phrase(re_match("a*?", Match), "a").
Match = "a"
; false.Match pattern only if followed by lookahead sub-expression.
?- phrase(re_match("a(?=b)b", Match), "ab").
Match = "ab"
; false.Syntax support for named capturing groups using re_match//2 for full pattern matching, and re_match_named//3 with re_group/3 to extract named captured subgroups.
?- phrase(re_match_named("(?P<first>[a-z]+) ([a-z]+) (?P<last>[a-z]+)", Match, Named), "john middle doe"), re_group(Named, first, First).
Match = "john middle doe"
Named = [last-[d,o,e],first-[j,o,h,n]]
First = "john"
; false.Enable case-insensitivity using inline flags.
?- phrase(re_match("(?i)abc", Match), "ABC").
Match = "ABC"
; false.Manually compile a pattern and execute matching.
?- re_compile("a*b", Compiled), phrase(re_match(Compiled, Match), "aaab").
Compiled = compiled_tree(star(sym(char(a),end,stp),sym(char(b),end,stp)),0)
Match = "aaab"
; false.Use DCG interface re_match//2 inside phrase/3.
?- phrase(re_match("a*b", Match), "aaabc", "c").
Match = "aaab"
; false.Use DCG interface re_match_groups//3 with groups inside phrase/3. Captured groups are returned in group-number order (left-to-right based on the position of their opening parentheses). See: https://docs.oracle.com/javase/tutorial/essential/regex/groups.html
?- phrase(re_match_groups("(a*)b", Match, Groups), "aaabc", "c").
Match = "aaab"
Groups = ["aaa"]
; false.Use re_match//2 with a pre-compiled pattern.
?- re_compile("a*b", Compiled), phrase(re_match(Compiled, Match), "aaabc", "c").
Compiled = compiled_tree(star(sym(char(a),end,stp),sym(char(b),end,stp)),0)
Match = "aaab"
; false.Use re_match_groups//3 with a pre-compiled pattern and group extraction. Captured groups are returned in group-number order (left-to-right based on the position of their opening parentheses). See: https://docs.oracle.com/javase/tutorial/essential/regex/groups.html
?- re_compile("(a*)b", Compiled), phrase(re_match_groups(Compiled, Match, Groups), "aaabc", "c").
Compiled = compiled_tree(cap_open(0,star(sym(char(a),end,stp),cap_close(0,sym(char(b),end,stp)))),1)
Match = "aaab"
Groups = ["aaa"]
; false.Access and verify the internal compilation cache.
?- re_clear_cache, phrase(re_match("c*d", Match), "cccd"), re_cache_info(Count, Keys).
Match = "cccd"
Count = 0
Keys = ""
; false.Clear the cache database and verify no patterns remain. Intended for rare situations where excessive compiled patterns cause high memory use.
?- re_clear_cache, phrase(re_match("c*d", Match), "cccd"), re_clear_cache, re_cache_info(CountAfter, KeysAfter).
CountAfter = 0
KeysAfter = ""
; false.Match pattern inside input using phrase/3.
?- phrase((..., re_match("aa", Match)), "bbbbaaccccc", Rest).
Match = "aa"
Rest = "ccccc"
; false.Match pattern inside input using phrase/2 (requires matching remaining suffix).
?- phrase((..., re_match("aa", Match), ...), "bbbbaaccccc").
Match = "aa"
; false.Extract groups from a pattern of three captures containing nested captures 4 deep. Captured groups are returned in group-number order (left-to-right based on the position of their opening parentheses). Nested groups follow their enclosing group. See: https://docs.oracle.com/javase/tutorial/essential/regex/groups.html
?- phrase(re_match_groups("(a(b(c(d))))(e(f(g(h))))(i(j(k(l))))", Match, Groups), "abcdefghijkl").
Match = "abcdefghijkl"
Groups = ["abcd", "bcd", "cd", "d", "efgh", "fgh", "gh", "h", "ijkl", "jkl", "kl", "l"]
; false.Match pattern and extract named capturing groups using re_match_named//3 and lookup using re_group/3.
?- phrase(re_match_named("(?P<first>[a-z]+) ([a-z]+) (?P<last>[a-z]+)", Match, Named), "john middle doe"), re_group(Named, first, First).
Match = "john middle doe"
Named = [last-[d,o,e],first-[j,o,h,n]]
First = "john"
; false.Match accented Latin characters.
?- phrase(re_match("café", Match), "café et croissant", Rest).
Match = "café"
Rest = " et croissant"
; false.Match Greek characters with Kleene plus quantifiers.
?- phrase(re_match("α+β+", Match), "αααβββ123", Rest).
Match = "αααβββ"
Rest = "123"
; false.Match characters using Unicode Greek range [α-ω].
?- phrase(re_match("[α-ω]+", Match), "αβγδεxyz", Rest).
Match = "αβγδε"
Rest = "xyz"
; false.Match Chinese characters with named capturing groups.
?- phrase(re_match_named("(?P<greeting>你好)-(?P<target>世界)", Match, Named), "你好-世界").
Match = "你好-世界"
Named = [target-[世,界],greeting-[你,好]]
; false.Match Japanese Hiragana characters.
?- phrase(re_match("こんにちは", Match), "こんにちは世界", Rest).
Match = "こんにちは"
Rest = "世界"
; false.Match Klingon script characters in Unicode Private Use Area (tlhIngan Hol).
?- phrase(re_match("", Match), " Hol", Rest).
Match = ""
Rest = " Hol"
; false.Match Emoji characters with quantifiers.
?- phrase(re_match("🚀+😀+", Match), "🚀🚀😀😀😀!foo", Rest).
Match = "🚀🚀😀😀😀"
Rest = "!foo"
; false.