GitHub Viewer
// Copyright 2022-2026 Herb Sutter
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Part of the Cppfront Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://github.com/hsutter/cppfront/blob/main/LICENSE for license information.
//===========================================================================
// Regex support
//===========================================================================
#ifndef CPP2_CPP2REGEX_H
#define CPP2_CPP2REGEX_H
template
using matcher_context_type = typename matcher::template context;
cpp2: namespace = {
regex: namespace = {
bstring: type == std::basic_string;
bview : type == std::basic_string_view;
//-----------------------------------------------------------------------
//
// Helper structures for the expression matching.
//
//-----------------------------------------------------------------------
//
// Structure for storing group information.
//
match_group: @struct type =
{
start: Iter = ();
end: Iter = ();
matched: bool = false;
}
// Return value for every matcher.
//
match_return: @struct type =
{
matched: bool = false;
pos: Iter = ();
}
// Modifiable state during matching.
//
match_context: type =
{
public begin : Iter;
public end : Iter;
private groups: std::array = ();
operator=: (out this, begin_: Iter, end_: Iter) = {
begin = begin_;
end = end_;
}
operator=: (out this, that) = {}
// String end and start positions
//
get_string_start: (in this) = begin;
get_string_end: (in this) = end;
// Getter and setter for groups
//
get_group: (in this, group) = groups[group];
get_group_end: (in this, group) -> int = {
if group >= max_groups || !groups[group].matched {
return 0;
}
return cpp2::unchecked_narrow( std::distance(begin, groups[group].end) );
}
get_group_start: (in this, group) -> int = {
if group >= max_groups || !groups[group].matched {
return 0;
}
return cpp2::unchecked_narrow( std::distance(begin, groups[group].start) );
}
get_group_string: (in this, group) -> std::string = {
if group >= max_groups || !groups[group].matched {
return "";
}
return std::string(groups[group].start, groups[group].end);
}
set_group_end: (inout this, group, pos) = {
groups[group].end = pos;
groups[group].matched = true;
}
set_group_invalid: (inout this, group) = {
groups[group].matched = false;
}
set_group_start: (inout this, group, pos) = {
groups[group].start = pos;
}
size: (in this) = max_groups;
// Misc functions
//
fail: (in this) = match_return(false, end);
pass: (in this, cur: Iter) = match_return(true, cur);
reset: (inout this) = {
for groups do (inout g) {
g.matched = false;
}
}
}
// Wrapper of context for reverse matches. Implements only the minimal interface for matching.
//
reverse_match_context: type =
{
public ReverseIter : type == std::reverse_iterator;
public forward_context : *match_context;
public begin : ReverseIter;
public end : ReverseIter;
operator=: (out this, forward_context_) = {
forward_context = forward_context_;
begin = std::make_reverse_iterator(forward_context*.end);
end = std::make_reverse_iterator(forward_context*.begin);
}
operator=: (out this, that) = {}
// String end and start positions
//
get_string_start: (in this) = end;
get_string_end: (in this) = begin;
// Getter and setter for groups
//
set_group_end: (inout this, group, pos) = {
forward_context*..set_group_end(group, (pos).base());
}
set_group_invalid: (inout this, group) = {
forward_context*..set_group_invalid(group);
}
set_group_start: (inout this, group, pos) = {
forward_context*..set_group_start(group, (pos).base());
}
// Misc functions
//
fail: (in this) = match_return(false, end);
pass: (in this, cur: ReverseIter) = match_return(true, cur);
}
// Helpers for creating wrappers of the match context.
//
make_forward_match_context: (inout ctx: match_context) -> forward _ = {
return ctx;
}
make_forward_match_context: (inout ctx: reverse_match_context) -> forward _ = {
return ctx.forward_context*;
}
make_reverse_match_context: (inout ctx: match_context) -> _ = {
return reverse_match_context(ctx&);
}
make_reverse_match_context: (inout ctx: reverse_match_context) -> forward _ = {
return ctx;
}
// Helpers for creating wrappers of the iterators.
//
cpp2_make_forward_iterator: (pos: Iter) -> _ = pos;
cpp2_make_forward_iterator: (pos: std::reverse_iterator) -> _ = pos.base();
cpp2_make_reverse_iterator: (pos: Iter) -> _ = std::make_reverse_iterator(pos);
cpp2_make_reverse_iterator: (pos: std::reverse_iterator) -> _ = pos;
// End function that returns a valid match.
//
true_end_func: @struct type =
{
operator(): (in this, cur, inout ctx) = ctx..pass(cur);
}
// Empty group reset function.
//
no_reset: @struct type =
{
operator(): (this, inout _:) = {}
}
// Evaluate func on destruction of the handle.
on_return: type =
{
func: Func;
operator=: (out this, f: Func) = {
func = f;
}
operator=: (move this) = {
func();
}
}
// Helper for auto deduction of the Func type.
make_on_return: (func: Func) = on_return(func);
//-----------------------------------------------------------------------
//
// Character classes for regular expressions.
//
//-----------------------------------------------------------------------
//
// Class syntax: Example: a
//
single_class_entry: type =
{
includes : (c: CharT) = c == C;
to_string: () = bstring(1, C);
}
// Class syntax: - Example: a-c
//
range_class_entry: type =
{
includes : (c: CharT) = Start