<commit_before>﻿/*----------------------------------------------------------
This Source Code Form is subject to the terms of the 
Mozilla Public License, v.2.0. If a copy of the MPL 
was not distributed with this file, You can obtain one 
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
using System.Linq;
using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;
using RegExp = System.Text.RegularExpressions;

namespace ScriptEngine.HostedScript.Library.RegexLib
{
    [ContextClass("РегулярноеВыражение", "Regex")]
    class RegExpImpl : AutoContext<RegExpImpl>
    {
        private RegExp.Regex _regex;
        private string _pattern;

        public RegExpImpl(string pattern)
        {
            _pattern = pattern;
            _regex = new RegExp.Regex(_pattern, RegExp.RegexOptions.IgnoreCase | RegExp.RegexOptions.Multiline );
        }

        /// <summary>
        /// Проверяет, что строка совпадает с шаблоном регулярного выражения.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Признак совпадения. Булево.</returns>
        [ContextMethod("Совпадает", "IsMatch")]
        public IValue IsMatch(string input, int startat = 0)
        {
            return ValueFactory.Create(_regex.IsMatch(input, startat));
        }

        /// <summary>
        /// Находит все совпадения в строке по шаблону регулярного выражения.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Коллекция совпадения (тип КоллекцияСовпаденийРегулярногоВыражения).</returns>
        [ContextMethod("НайтиСовпадения", "Matches")]
        public IValue Matches(string input, int startat = 0)
        {
            return new MatchCollection(_regex.Matches(input, startat));
        }

        /// <summary>
        /// Разделяет исходную строку на части, используя как разделитель заданное регулярное выражение.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="count">Число. Необязательный параметр. По-умолчанию 0 (искать все). Содержит количество искомых элементов.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Массив полученных строк.</returns>
        [ContextMethod("Разделить", "Split")]
        public IValue Split(string input, int count = 0, int startat = 0)
        {
            string[] arrParsed = _regex.Split(input, count, startat);
            return new ArrayImpl(arrParsed.Select(x => ValueFactory.Create(x)));
        }

        /// <summary>
        /// Заменяет в исходной строке все вхождения регулярного выражения на СтрокаЗамены.
        /// В строке замены можно использовать ссылки на захваченные группы, как $n, где n - номер захваченной группы ($0 - все захваченное выражение).
        /// </summary>
        /// <param name="inputString">Строка. Текст, в котором необходимо выполнить замены.</param>
        /// <param name="replacement">Строка. Текст, который будет вставляться в места замены.</param>
        /// <returns>Строку-результат замены.</returns>
        [ContextMethod("Заменить", "Replace")]
        public string Replace(string input, string replacement)
        {
            return _regex.Replace(input, replacement);
        }

        /// <summary>
        /// Признак Не учитывать регистр символов. Булево
        /// </summary>
        [ContextProperty("ИгнорироватьРегистр", "IgnoreCase")]
        public bool IgnoreCase
        {
            get { return _regex.Options.HasFlag( RegExp.RegexOptions.IgnoreCase ); }
            set { SetOption(value, RegExp.RegexOptions.IgnoreCase); }
        }

        /// <summary>
        /// Признак выполнения многострочного поиска. Булево
        /// </summary>
        [ContextProperty("Многострочный", "Multiline")]
        public bool Multiline
        {
            get { return _regex.Options.HasFlag(RegExp.RegexOptions.Multiline); }
            set { SetOption(value, RegExp.RegexOptions.Multiline); }
        }

        /// <summary>
        /// Конструктор создания регулярного выражения по заданному шаблону.
        /// </summary>
        /// <param name="patternString">Строка-шаблон регулярного выражения.</param>
        [ScriptConstructor(Name = "По регулярному выражению")]
        public static IRuntimeContextInstance Constructor(IValue pattern)
        {
            var regex = new RegExpImpl(pattern.AsString());
            return regex;
        }

        private void SetOption(bool value, RegExp.RegexOptions option)
        {
                var options = _regex.Options;
                if (value)
                    options |= option;
                else
                    options &= ~option;

                //приходится пересоздавать объект, т.к. опции объекта по умолчанию только read-only
                _regex = new RegExp.Regex(_pattern, options);
        }
    }
}
<commit_msg>Вместо IValue использую реальный тип для возвращаемых значений see #115<commit_after>﻿/*----------------------------------------------------------
This Source Code Form is subject to the terms of the 
Mozilla Public License, v.2.0. If a copy of the MPL 
was not distributed with this file, You can obtain one 
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
using System.Linq;
using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;
using RegExp = System.Text.RegularExpressions;

namespace ScriptEngine.HostedScript.Library.RegexLib
{
    [ContextClass("РегулярноеВыражение", "Regex")]
    class RegExpImpl : AutoContext<RegExpImpl>
    {
        private RegExp.Regex _regex;
        private string _pattern;

        public RegExpImpl(string pattern)
        {
            _pattern = pattern;
            _regex = new RegExp.Regex(_pattern, RegExp.RegexOptions.IgnoreCase | RegExp.RegexOptions.Multiline );
        }

        /// <summary>
        /// Проверяет, что строка совпадает с шаблоном регулярного выражения.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Признак совпадения. Булево.</returns>
        [ContextMethod("Совпадает", "IsMatch")]
        public IValue IsMatch(string input, int startat = 0)
        {
            return ValueFactory.Create(_regex.IsMatch(input, startat));
        }

        /// <summary>
        /// Находит все совпадения в строке по шаблону регулярного выражения.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Коллекция совпадения (тип КоллекцияСовпаденийРегулярногоВыражения).</returns>
        [ContextMethod("НайтиСовпадения", "Matches")]
        public MatchCollection Matches(string input, int startat = 0)
        {
            return new MatchCollection(_regex.Matches(input, startat));
        }

        /// <summary>
        /// Разделяет исходную строку на части, используя как разделитель заданное регулярное выражение.
        /// </summary>
        /// <param name="inputString">Строка, которая проверяется.</param>
        /// <param name="count">Число. Необязательный параметр. По-умолчанию 0 (искать все). Содержит количество искомых элементов.</param>
        /// <param name="startAt">Число. Необязательный параметр. По-умолчанию 0. Содержит стартовую позицию, начиная с которой надо анализировать текст. Нумерация позиций в отличии от 1С начинается с 0</param>
        /// <returns>Массив полученных строк.</returns>
        [ContextMethod("Разделить", "Split")]
        public ArrayImpl Split(string input, int count = 0, int startat = 0)
        {
            string[] arrParsed = _regex.Split(input, count, startat);
            return new ArrayImpl(arrParsed.Select(x => ValueFactory.Create(x)));
        }

        /// <summary>
        /// Заменяет в исходной строке все вхождения регулярного выражения на СтрокаЗамены.
        /// В строке замены можно использовать ссылки на захваченные группы, как $n, где n - номер захваченной группы ($0 - все захваченное выражение).
        /// </summary>
        /// <param name="inputString">Строка. Текст, в котором необходимо выполнить замены.</param>
        /// <param name="replacement">Строка. Текст, который будет вставляться в места замены.</param>
        /// <returns>Строку-результат замены.</returns>
        [ContextMethod("Заменить", "Replace")]
        public string Replace(string input, string replacement)
        {
            return _regex.Replace(input, replacement);
        }

        /// <summary>
        /// Признак Не учитывать регистр символов. Булево
        /// </summary>
        [ContextProperty("ИгнорироватьРегистр", "IgnoreCase")]
        public bool IgnoreCase
        {
            get { return _regex.Options.HasFlag( RegExp.RegexOptions.IgnoreCase ); }
            set { SetOption(value, RegExp.RegexOptions.IgnoreCase); }
        }

        /// <summary>
        /// Признак выполнения многострочного поиска. Булево
        /// </summary>
        [ContextProperty("Многострочный", "Multiline")]
        public bool Multiline
        {
            get { return _regex.Options.HasFlag(RegExp.RegexOptions.Multiline); }
            set { SetOption(value, RegExp.RegexOptions.Multiline); }
        }

        /// <summary>
        /// Конструктор создания регулярного выражения по заданному шаблону.
        /// </summary>
        /// <param name="patternString">Строка-шаблон регулярного выражения.</param>
        [ScriptConstructor(Name = "По регулярному выражению")]
        public static IRuntimeContextInstance Constructor(IValue pattern)
        {
            var regex = new RegExpImpl(pattern.AsString());
            return regex;
        }

        private void SetOption(bool value, RegExp.RegexOptions option)
        {
                var options = _regex.Options;
                if (value)
                    options |= option;
                else
                    options &= ~option;

                //приходится пересоздавать объект, т.к. опции объекта по умолчанию только read-only
                _regex = new RegExp.Regex(_pattern, options);
        }
    }
}

{'fraction_non_alphanumeric': 0.12502224595123687, 'fraction_numerical': 0.0036483360028474817, 'mean_word_length': 2.2463893703061815, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '821897', 'n_tokens_mistral': 3497, 'n_tokens_neox': 3851, 'n_words': 829}